2 * iphlpapi dll implementation
4 * Copyright (C) 2003 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <sys/types.h>
26 #ifdef HAVE_NETINET_IN_H
27 # include <netinet/in.h>
29 #ifdef HAVE_ARPA_NAMESER_H
30 # include <arpa/nameser.h>
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
46 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
49 case DLL_PROCESS_ATTACH:
50 DisableThreadLibraryCalls( hinstDLL );
54 case DLL_PROCESS_DETACH:
61 /******************************************************************
62 * AddIPAddress (IPHLPAPI.@)
71 * NTEInstance [In/Out]
78 DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance)
81 /* marking Win2K+ functions not supported */
82 return ERROR_NOT_SUPPORTED;
86 /******************************************************************
87 * AllocateAndGetIfTableFromStack (IPHLPAPI.@)
92 * ppIfTable [Out] -- pointer into which the MIB_IFTABLE is
93 * allocated and returned.
94 * bOrder [In] -- passed to GetIfTable to order the table
95 * heap [In] -- heap from which the table is allocated
96 * flags [In] -- flags to HeapAlloc
98 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
99 * GetIfTable returns otherwise
102 DWORD WINAPI AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable,
103 BOOL bOrder, HANDLE heap, DWORD flags)
108 ret = ERROR_INVALID_PARAMETER;
112 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
113 if (ret == ERROR_INSUFFICIENT_BUFFER) {
114 *ppIfTable = (PMIB_IFTABLE)HeapAlloc(heap, flags, dwSize);
115 ret = GetIfTable(*ppIfTable, &dwSize, bOrder);
122 /******************************************************************
123 * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@)
128 * ppIpAddrTable [Out]
129 * bOrder [In] -- passed to GetIpAddrTable to order the table
130 * heap [In] -- heap from which the table is allocated
131 * flags [In] -- flags to HeapAlloc
138 DWORD WINAPI AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
139 BOOL bOrder, HANDLE heap, DWORD flags)
144 ret = ERROR_INVALID_PARAMETER;
148 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
149 if (ret == ERROR_INSUFFICIENT_BUFFER) {
150 *ppIpAddrTable = (PMIB_IPADDRTABLE)HeapAlloc(heap, flags, dwSize);
151 ret = GetIpAddrTable(*ppIpAddrTable, &dwSize, bOrder);
158 /******************************************************************
159 * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
162 * ppIpForwardTable [Out] -- pointer into which the MIB_IPFORWARDTABLE is
163 * allocated and returned.
164 * bOrder [In] -- passed to GetIfTable to order the table
165 * heap [In] -- heap from which the table is allocated
166 * flags [In] -- flags to HeapAlloc
168 * RETURNS -- ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
169 * GetIpForwardTable returns otherwise
172 DWORD WINAPI AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *
173 ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags)
177 if (!ppIpForwardTable)
178 ret = ERROR_INVALID_PARAMETER;
182 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
183 if (ret == ERROR_INSUFFICIENT_BUFFER) {
184 *ppIpForwardTable = (PMIB_IPFORWARDTABLE)HeapAlloc(heap, flags, dwSize);
185 ret = GetIpForwardTable(*ppIpForwardTable, &dwSize, bOrder);
192 /******************************************************************
193 * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@)
199 * bOrder [In] -- passed to GetIpNetTable to order the table
200 * heap [In] -- heap from which the table is allocated
201 * flags [In] -- flags to HeapAlloc
208 DWORD WINAPI AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable,
209 BOOL bOrder, HANDLE heap, DWORD flags)
214 ret = ERROR_INVALID_PARAMETER;
218 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
219 if (ret == ERROR_INSUFFICIENT_BUFFER) {
220 *ppIpNetTable = (PMIB_IPNETTABLE)HeapAlloc(heap, flags, dwSize);
221 ret = GetIpNetTable(*ppIpNetTable, &dwSize, bOrder);
228 /******************************************************************
229 * AllocateAndGetTcpTableFromStack (IPHLPAPI.@)
235 * bOrder [In] -- passed to GetTcpTable to order the table
236 * heap [In] -- heap from which the table is allocated
237 * flags [In] -- flags to HeapAlloc
244 DWORD WINAPI AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
245 BOOL bOrder, HANDLE heap, DWORD flags)
250 ret = ERROR_INVALID_PARAMETER;
254 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
255 if (ret == ERROR_INSUFFICIENT_BUFFER) {
256 *ppTcpTable = (PMIB_TCPTABLE)HeapAlloc(heap, flags, dwSize);
257 ret = GetTcpTable(*ppTcpTable, &dwSize, bOrder);
264 /******************************************************************
265 * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
271 * bOrder [In] -- passed to GetUdpTable to order the table
272 * heap [In] -- heap from which the table is allocated
273 * flags [In] -- flags to HeapAlloc
280 DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
281 BOOL bOrder, HANDLE heap, DWORD flags)
286 ret = ERROR_INVALID_PARAMETER;
290 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
291 if (ret == ERROR_INSUFFICIENT_BUFFER) {
292 *ppUdpTable = (PMIB_UDPTABLE)HeapAlloc(heap, flags, dwSize);
293 ret = GetUdpTable(*ppUdpTable, &dwSize, bOrder);
300 /******************************************************************
301 * CreateIpForwardEntry (IPHLPAPI.@)
313 DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
315 /* could use SIOCADDRT, not sure I want to */
321 /******************************************************************
322 * CreateIpNetEntry (IPHLPAPI.@)
334 DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
336 /* could use SIOCSARP on systems that support it, not sure I want to */
342 /******************************************************************
343 * CreateProxyArpEntry (IPHLPAPI.@)
357 DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
360 /* marking Win2K+ functions not supported */
361 return ERROR_NOT_SUPPORTED;
365 /******************************************************************
366 * DeleteIPAddress (IPHLPAPI.@)
378 DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
381 /* marking Win2K+ functions not supported */
382 return ERROR_NOT_SUPPORTED;
386 /******************************************************************
387 * DeleteIpForwardEntry (IPHLPAPI.@)
399 DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
401 /* could use SIOCDELRT, not sure I want to */
407 /******************************************************************
408 * DeleteIpNetEntry (IPHLPAPI.@)
420 DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
422 /* could use SIOCDARP on systems that support it, not sure I want to */
428 /******************************************************************
429 * DeleteProxyArpEntry (IPHLPAPI.@)
443 DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex)
446 /* marking Win2K+ functions not supported */
447 return ERROR_NOT_SUPPORTED;
451 /******************************************************************
452 * EnableRouter (IPHLPAPI.@)
458 * pOverlapped [In/Out]
465 DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped)
468 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
469 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
470 marking Win2K+ functions not supported */
471 return ERROR_NOT_SUPPORTED;
475 /******************************************************************
476 * FlushIpNetTable (IPHLPAPI.@)
488 DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex)
491 /* this flushes the arp cache of the given index
492 marking Win2K+ functions not supported */
493 return ERROR_NOT_SUPPORTED;
497 /******************************************************************
498 * GetAdapterIndex (IPHLPAPI.@)
503 * AdapterName [In/Out]
511 DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
514 /* marking Win2K+ functions not supported */
515 return ERROR_NOT_SUPPORTED;
519 /******************************************************************
520 * GetAdaptersInfo (IPHLPAPI.@)
525 * pAdapterInfo [In/Out]
526 * pOutBufLen [In/Out]
533 DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
538 ret = ERROR_INVALID_PARAMETER;
540 DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces();
542 if (numNonLoopbackInterfaces > 0) {
543 /* this calculation assumes only one address in the IP_ADDR_STRING lists.
544 that's okay, because:
545 - we don't get multiple addresses per adapter anyway
546 - we don't know about per-adapter gateways
547 - we don't know about DHCP or WINS (and these must be single anyway) */
548 ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces;
550 if (!pAdapterInfo || *pOutBufLen < size) {
552 ret = ERROR_BUFFER_OVERFLOW;
555 InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable();
558 size = sizeof(IP_ADAPTER_INFO) * table->numIndexes;
559 if (*pOutBufLen < size) {
561 ret = ERROR_INSUFFICIENT_BUFFER;
566 memset(pAdapterInfo, 0, size);
567 for (ndx = 0; ndx < table->numIndexes; ndx++) {
568 PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx];
569 DWORD addrLen = sizeof(ptr->Address), type;
571 /* on Win98 this is left empty, but whatever */
572 strncpy(ptr->AdapterName,
573 getInterfaceNameByIndex(table->indexes[ndx]),
574 sizeof(ptr->AdapterName));
575 ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0';
576 getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen,
577 ptr->Address, &type);
578 /* MS defines address length and type as UINT in some places and
579 DWORD in others, **sigh**. Don't want to assume that PUINT and
580 PDWORD are equiv (64-bit?) */
581 ptr->AddressLength = addrLen;
583 ptr->Index = table->indexes[ndx];
584 toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]),
585 ptr->IpAddressList.IpAddress.String);
586 toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]),
587 ptr->IpAddressList.IpMask.String);
588 if (ndx < table->numIndexes - 1)
589 ptr->Next = &pAdapterInfo[ndx + 1];
598 ret = ERROR_OUTOFMEMORY;
608 /******************************************************************
609 * GetBestInterface (IPHLPAPI.@)
615 * pdwBestIfIndex [In/Out]
622 DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
627 ret = ERROR_INVALID_PARAMETER;
629 MIB_IPFORWARDROW ipRow;
631 ret = GetBestRoute(dwDestAddr, 0, &ipRow);
632 if (ret == ERROR_SUCCESS)
633 *pdwBestIfIndex = ipRow.dwForwardIfIndex;
639 /******************************************************************
640 * GetBestRoute (IPHLPAPI.@)
654 DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute)
656 PMIB_IPFORWARDTABLE table;
660 return ERROR_INVALID_PARAMETER;
662 AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
664 DWORD ndx, matchedBits, matchedNdx = 0;
666 for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
667 if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
668 (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
669 DWORD numShifts, mask;
671 for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
672 mask && !(mask & 1); mask >>= 1, numShifts++)
674 if (numShifts > matchedBits) {
675 matchedBits = numShifts;
680 memcpy(pBestRoute, &table->table[matchedNdx], sizeof(MIB_IPFORWARDROW));
681 HeapFree(GetProcessHeap(), 0, table);
685 ret = ERROR_OUTOFMEMORY;
690 /******************************************************************
691 * GetFriendlyIfIndex (IPHLPAPI.@)
703 DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
705 /* windows doesn't validate these, either, just makes sure the top byte is
706 cleared. I assume my ifenum module never gives an index with the top
712 /******************************************************************
713 * GetIcmpStatistics (IPHLPAPI.@)
725 DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats)
727 return getICMPStats(pStats);
731 /******************************************************************
732 * GetIfEntry (IPHLPAPI.@)
744 DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
750 return ERROR_INVALID_PARAMETER;
752 name = getInterfaceNameByIndex(pIfRow->dwIndex);
754 ret = getInterfaceEntryByName(name, pIfRow);
756 ret = getInterfaceStatsByName(name, pIfRow);
759 ret = ERROR_INVALID_DATA;
764 static int IfTableSorter(const void *a, const void *b)
769 ret = ((PMIB_IFROW)a)->dwIndex - ((PMIB_IFROW)b)->dwIndex;
776 /******************************************************************
777 * GetIfTable (IPHLPAPI.@)
791 DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
796 ret = ERROR_INVALID_PARAMETER;
798 DWORD numInterfaces = getNumInterfaces();
799 ULONG size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW);
801 if (!pIfTable || *pdwSize < size) {
803 ret = ERROR_INSUFFICIENT_BUFFER;
806 InterfaceIndexTable *table = getInterfaceIndexTable();
809 size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) *
811 if (*pdwSize < size) {
813 ret = ERROR_INSUFFICIENT_BUFFER;
818 pIfTable->dwNumEntries = 0;
819 for (ndx = 0; ndx < table->numIndexes; ndx++) {
820 pIfTable->table[ndx].dwIndex = table->indexes[ndx];
821 GetIfEntry(&pIfTable->table[ndx]);
822 pIfTable->dwNumEntries++;
825 qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
832 ret = ERROR_OUTOFMEMORY;
839 /******************************************************************
840 * GetInterfaceInfo (IPHLPAPI.@)
846 * dwOutBufLen [In/Out]
853 DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen)
858 ret = ERROR_INVALID_PARAMETER;
860 DWORD numInterfaces = getNumInterfaces();
861 ULONG size = sizeof(IP_INTERFACE_INFO) + (numInterfaces - 1) *
862 sizeof(IP_ADAPTER_INDEX_MAP);
864 if (!pIfTable || *dwOutBufLen < size) {
866 ret = ERROR_INSUFFICIENT_BUFFER;
869 InterfaceIndexTable *table = getInterfaceIndexTable();
872 size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes - 1) *
873 sizeof(IP_ADAPTER_INDEX_MAP);
874 if (*dwOutBufLen < size) {
876 ret = ERROR_INSUFFICIENT_BUFFER;
881 pIfTable->NumAdapters = 0;
882 for (ndx = 0; ndx < table->numIndexes; ndx++) {
883 const char *walker, *name;
886 pIfTable->Adapter[ndx].Index = table->indexes[ndx];
887 name = getInterfaceNameByIndex(table->indexes[ndx]);
888 for (walker = name, assigner = pIfTable->Adapter[ndx].Name;
890 assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1;
891 walker++, assigner++)
894 pIfTable->NumAdapters++;
901 ret = ERROR_OUTOFMEMORY;
908 static int IpAddrTableSorter(const void *a, const void *b)
913 ret = ((PMIB_IPADDRROW)a)->dwAddr - ((PMIB_IPADDRROW)b)->dwAddr;
920 /******************************************************************
921 * GetIpAddrTable (IPHLPAPI.@)
926 * pIpAddrTable [In/Out]
935 DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder)
940 ret = ERROR_INVALID_PARAMETER;
942 DWORD numInterfaces = getNumInterfaces();
943 ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) *
944 sizeof(MIB_IPADDRROW);
946 if (!pIpAddrTable || *pdwSize < size) {
948 ret = ERROR_INSUFFICIENT_BUFFER;
951 InterfaceIndexTable *table = getInterfaceIndexTable();
954 size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) *
955 sizeof(MIB_IPADDRROW);
956 if (*pdwSize < size) {
958 ret = ERROR_INSUFFICIENT_BUFFER;
963 pIpAddrTable->dwNumEntries = 0;
964 for (ndx = 0; ndx < table->numIndexes; ndx++) {
965 pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx];
966 pIpAddrTable->table[ndx].dwAddr =
967 getInterfaceIPAddrByIndex(table->indexes[ndx]);
968 pIpAddrTable->table[ndx].dwMask =
969 getInterfaceMaskByIndex(table->indexes[ndx]);
970 pIpAddrTable->table[ndx].dwBCastAddr =
971 getInterfaceBCastAddrByIndex(table->indexes[ndx]);
972 /* FIXME: hardcoded reasm size, not sure where to get it */
973 pIpAddrTable->table[ndx].dwReasmSize = 65535;
974 pIpAddrTable->table[ndx].unused1 = 0;
975 pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */
976 pIpAddrTable->dwNumEntries++;
979 qsort(pIpAddrTable->table, pIpAddrTable->dwNumEntries,
980 sizeof(MIB_IPADDRROW), IpAddrTableSorter);
986 ret = ERROR_OUTOFMEMORY;
993 static int IpForwardTableSorter(const void *a, const void *b)
998 PMIB_IPFORWARDROW rowA = (PMIB_IPFORWARDROW)a, rowB = (PMIB_IPFORWARDROW)b;
1000 ret = rowA->dwForwardDest - rowB->dwForwardDest;
1002 ret = rowA->dwForwardProto - rowB->dwForwardProto;
1004 ret = rowA->dwForwardPolicy - rowB->dwForwardPolicy;
1006 ret = rowA->dwForwardNextHop - rowB->dwForwardNextHop;
1016 /******************************************************************
1017 * GetIpForwardTable (IPHLPAPI.@)
1022 * pIpForwardTable [In/Out]
1031 DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder)
1036 ret = ERROR_INVALID_PARAMETER;
1038 DWORD numRoutes = getNumRoutes();
1039 ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) *
1040 sizeof(MIB_IPFORWARDROW);
1042 if (!pIpForwardTable || *pdwSize < sizeNeeded) {
1043 *pdwSize = sizeNeeded;
1044 ret = ERROR_INSUFFICIENT_BUFFER;
1047 RouteTable *table = getRouteTable();
1049 sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) *
1050 sizeof(MIB_IPFORWARDROW);
1051 if (*pdwSize < sizeNeeded) {
1052 *pdwSize = sizeNeeded;
1053 ret = ERROR_INSUFFICIENT_BUFFER;
1058 pIpForwardTable->dwNumEntries = table->numRoutes;
1059 for (ndx = 0; ndx < numRoutes; ndx++) {
1060 pIpForwardTable->table[ndx].dwForwardIfIndex =
1061 table->routes[ndx].ifIndex;
1062 pIpForwardTable->table[ndx].dwForwardDest =
1063 table->routes[ndx].dest;
1064 pIpForwardTable->table[ndx].dwForwardMask =
1065 table->routes[ndx].mask;
1066 pIpForwardTable->table[ndx].dwForwardPolicy = 0;
1067 pIpForwardTable->table[ndx].dwForwardNextHop =
1068 table->routes[ndx].gateway;
1069 /* FIXME: this type is appropriate for local interfaces; may not
1070 always be appropriate */
1071 pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
1072 /* FIXME: other protos might be appropriate, e.g. the default route
1073 is typically set with MIB_IPPROTO_NETMGMT instead */
1074 pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL;
1075 /* punt on age and AS */
1076 pIpForwardTable->table[ndx].dwForwardAge = 0;
1077 pIpForwardTable->table[ndx].dwForwardNextHopAS = 0;
1078 pIpForwardTable->table[ndx].dwForwardMetric1 =
1079 table->routes[ndx].metric;
1080 /* rest of the metrics are 0.. */
1081 pIpForwardTable->table[ndx].dwForwardMetric2 = 0;
1082 pIpForwardTable->table[ndx].dwForwardMetric3 = 0;
1083 pIpForwardTable->table[ndx].dwForwardMetric4 = 0;
1084 pIpForwardTable->table[ndx].dwForwardMetric5 = 0;
1087 qsort(pIpForwardTable->table, pIpForwardTable->dwNumEntries,
1088 sizeof(MIB_IPFORWARDROW), IpForwardTableSorter);
1094 ret = ERROR_OUTOFMEMORY;
1101 static int IpNetTableSorter(const void *a, const void *b)
1106 ret = ((PMIB_IPNETROW)a)->dwAddr - ((PMIB_IPNETROW)b)->dwAddr;
1113 /******************************************************************
1114 * GetIpNetTable (IPHLPAPI.@)
1119 * pIpNetTable [In/Out]
1128 DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
1133 ret = ERROR_INVALID_PARAMETER;
1135 DWORD numEntries = getNumArpEntries();
1136 ULONG size = sizeof(MIB_IPNETTABLE) + (numEntries - 1) *
1137 sizeof(MIB_IPNETROW);
1139 if (!pIpNetTable || *pdwSize < size) {
1141 ret = ERROR_INSUFFICIENT_BUFFER;
1144 PMIB_IPNETTABLE table = getArpTable();
1147 size = sizeof(MIB_IPNETTABLE) + (table->dwNumEntries - 1) *
1148 sizeof(MIB_IPNETROW);
1149 if (*pdwSize < size) {
1151 ret = ERROR_INSUFFICIENT_BUFFER;
1154 memcpy(pIpNetTable, table, size);
1156 qsort(pIpNetTable->table, pIpNetTable->dwNumEntries,
1157 sizeof(MIB_IPNETROW), IpNetTableSorter);
1163 ret = ERROR_OUTOFMEMORY;
1170 /******************************************************************
1171 * GetIpStatistics (IPHLPAPI.@)
1183 DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats)
1185 return getIPStats(pStats);
1189 /******************************************************************
1190 * GetNetworkParams (IPHLPAPI.@)
1195 * pFixedInfo [In/Out]
1196 * pOutBufLen [In/Out]
1203 DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
1209 return ERROR_INVALID_PARAMETER;
1212 size = sizeof(FIXED_INFO) + (_res.nscount > 0 ? (_res.nscount - 1) *
1213 sizeof(IP_ADDR_STRING) : 0);
1214 if (!pFixedInfo || *pOutBufLen < size) {
1216 return ERROR_BUFFER_OVERFLOW;
1219 memset(pFixedInfo, 0, size);
1220 size = sizeof(pFixedInfo->HostName);
1221 GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size);
1222 size = sizeof(pFixedInfo->DomainName);
1223 GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size);
1224 if (_res.nscount > 0) {
1225 PIP_ADDR_STRING ptr;
1228 for (i = 0, ptr = &pFixedInfo->DnsServerList; i < _res.nscount && ptr;
1229 i++, ptr = ptr->Next) {
1230 toIPAddressString(_res.nsaddr_list[i].sin_addr.s_addr,
1231 ptr->IpAddress.String);
1232 if (i == _res.nscount - 1)
1235 ptr->Next = (PIP_ADDR_STRING)((LPBYTE)pFixedInfo + sizeof(FIXED_INFO));
1237 ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDR_STRING));
1240 pFixedInfo->NodeType = HYBRID_NODETYPE;
1241 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1242 "\\SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &hKey)
1245 DWORD size = sizeof(pFixedInfo->ScopeId);
1247 RegQueryValueExA(hKey, "ScopeID", NULL, NULL, pFixedInfo->ScopeId, &size);
1251 /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward
1252 I suppose could also check for a listener on port 53 to set EnableDns */
1257 /******************************************************************
1258 * GetNumberOfInterfaces (IPHLPAPI.@)
1270 DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf)
1275 ret = ERROR_INVALID_PARAMETER;
1277 *pdwNumIf = getNumInterfaces();
1284 /******************************************************************
1285 * GetPerAdapterInfo (IPHLPAPI.@)
1291 * pPerAdapterInfo [In/Out]
1292 * pOutBufLen [In/Out]
1299 DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
1302 /* marking Win2K+ functions not supported */
1303 return ERROR_NOT_SUPPORTED;
1307 /******************************************************************
1308 * GetRTTAndHopCount (IPHLPAPI.@)
1313 * DestIpAddress [In]
1323 BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT)
1330 /******************************************************************
1331 * GetTcpStatistics (IPHLPAPI.@)
1343 DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats)
1345 return getTCPStats(pStats);
1349 static int TcpTableSorter(const void *a, const void *b)
1354 PMIB_TCPROW rowA = (PMIB_TCPROW)a, rowB = (PMIB_TCPROW)b;
1356 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1358 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1360 ret = rowA->dwRemoteAddr - rowB->dwRemoteAddr;
1362 ret = rowA->dwRemotePort - rowB->dwRemotePort;
1372 /******************************************************************
1373 * GetTcpTable (IPHLPAPI.@)
1378 * pTcpTable [In/Out]
1387 DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
1392 ret = ERROR_INVALID_PARAMETER;
1394 DWORD numEntries = getNumTcpEntries();
1395 ULONG size = sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW);
1397 if (!pTcpTable || *pdwSize < size) {
1399 ret = ERROR_INSUFFICIENT_BUFFER;
1402 PMIB_TCPTABLE table = getTcpTable();
1405 size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) *
1407 if (*pdwSize < size) {
1409 ret = ERROR_INSUFFICIENT_BUFFER;
1412 memcpy(pTcpTable, table, size);
1414 qsort(pTcpTable->table, pTcpTable->dwNumEntries,
1415 sizeof(MIB_TCPROW), TcpTableSorter);
1421 ret = ERROR_OUTOFMEMORY;
1428 /******************************************************************
1429 * GetUdpStatistics (IPHLPAPI.@)
1441 DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats)
1443 return getUDPStats(pStats);
1447 static int UdpTableSorter(const void *a, const void *b)
1452 PMIB_UDPROW rowA = (PMIB_UDPROW)a, rowB = (PMIB_UDPROW)b;
1454 ret = rowA->dwLocalAddr - rowB->dwLocalAddr;
1456 ret = rowA->dwLocalPort - rowB->dwLocalPort;
1464 /******************************************************************
1465 * GetUdpTable (IPHLPAPI.@)
1470 * pUdpTable [In/Out]
1479 DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
1484 ret = ERROR_INVALID_PARAMETER;
1486 DWORD numEntries = getNumUdpEntries();
1487 ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW);
1489 if (!pUdpTable || *pdwSize < size) {
1491 ret = ERROR_INSUFFICIENT_BUFFER;
1494 PMIB_UDPTABLE table = getUdpTable();
1497 size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) *
1499 if (*pdwSize < size) {
1501 ret = ERROR_INSUFFICIENT_BUFFER;
1504 memcpy(pUdpTable, table, size);
1506 qsort(pUdpTable->table, pUdpTable->dwNumEntries,
1507 sizeof(MIB_UDPROW), UdpTableSorter);
1513 ret = ERROR_OUTOFMEMORY;
1520 /******************************************************************
1521 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
1526 * pIPIfInfo [In/Out]
1527 * dwOutBufLen [In/Out]
1534 DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
1536 /* a unidirectional adapter?? not bloody likely! */
1537 return ERROR_NOT_SUPPORTED;
1541 /******************************************************************
1542 * IpReleaseAddress (IPHLPAPI.@)
1547 * AdapterInfo [In/Out]
1554 DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1556 /* not a stub, never going to support this (and I never mark an adapter as
1557 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1558 return ERROR_NOT_SUPPORTED;
1562 /******************************************************************
1563 * IpRenewAddress (IPHLPAPI.@)
1568 * AdapterInfo [In/Out]
1575 DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
1577 /* not a stub, never going to support this (and I never mark an adapter as
1578 DHCP enabled, see GetAdaptersInfo, so this should never get called) */
1579 return ERROR_NOT_SUPPORTED;
1583 /******************************************************************
1584 * NotifyAddrChange (IPHLPAPI.@)
1590 * overlapped [In/Out]
1597 DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1600 /* marking Win2K+ functions not supported */
1601 return ERROR_NOT_SUPPORTED;
1605 /******************************************************************
1606 * NotifyRouteChange (IPHLPAPI.@)
1612 * overlapped [In/Out]
1619 DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
1622 /* marking Win2K+ functions not supported */
1623 return ERROR_NOT_SUPPORTED;
1627 /******************************************************************
1628 * SendARP (IPHLPAPI.@)
1636 * PhyAddrLen [In/Out]
1643 DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
1646 /* marking Win2K+ functions not supported */
1647 return ERROR_NOT_SUPPORTED;
1651 /******************************************************************
1652 * SetIfEntry (IPHLPAPI.@)
1664 DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow)
1666 /* this is supposed to set an administratively interface up or down.
1667 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
1668 this sort of down is indistinguishable from other sorts of down (e.g. no
1671 return ERROR_NOT_SUPPORTED;
1675 /******************************************************************
1676 * SetIpForwardEntry (IPHLPAPI.@)
1688 DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
1690 /* this is to add a route entry, how's it distinguishable from
1691 CreateIpForwardEntry?
1692 could use SIOCADDRT, not sure I want to */
1698 /******************************************************************
1699 * SetIpNetEntry (IPHLPAPI.@)
1704 * pArpEntry [In/Out]
1711 DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry)
1713 /* same as CreateIpNetEntry here, could use SIOCSARP, not sure I want to */
1719 /******************************************************************
1720 * SetIpStatistics (IPHLPAPI.@)
1732 DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats)
1739 /******************************************************************
1740 * SetIpTTL (IPHLPAPI.@)
1752 DWORD WINAPI SetIpTTL(UINT nTTL)
1754 /* could echo nTTL > /proc/net/sys/net/ipv4/ip_default_ttl, not sure I
1755 want to. Could map EACCESS to ERROR_ACCESS_DENIED, I suppose */
1761 /******************************************************************
1762 * SetTcpEntry (IPHLPAPI.@)
1774 DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow)
1781 /******************************************************************
1782 * UnenableRouter (IPHLPAPI.@)
1787 * pOverlapped [In/Out]
1788 * lpdwEnableCount [In/Out]
1795 DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount)
1798 /* could echo "0" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
1799 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
1800 marking Win2K+ functions not supported */
1801 return ERROR_NOT_SUPPORTED;