2 * iphlpapi dll implementation
4 * Copyright (C) 2003,2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <sys/types.h>
27 #ifdef HAVE_NETINET_IN_H
28 # include <netinet/in.h>
30 #ifdef HAVE_ARPA_INET_H
31 # include <arpa/inet.h>
34 #define NONAMELESSUNION
35 #define NONAMELESSSTRUCT
51 #include "tcpestats.h"
52 #include "ip2string.h"
56 #include "wine/debug.h"
57 #include "wine/unicode.h"
58 #include "wine/heap.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi
);
63 #define IF_NAMESIZE 16
67 #define INADDR_NONE ~0UL
70 #define CHARS_IN_GUID 39
72 DWORD WINAPI
AllocateAndGetIfTableFromStack( MIB_IFTABLE
**table
, BOOL sort
, HANDLE heap
, DWORD flags
);
73 DWORD WINAPI
AllocateAndGetIpAddrTableFromStack( MIB_IPADDRTABLE
**table
, BOOL sort
, HANDLE heap
, DWORD flags
);
75 static const NPI_MODULEID
*ip_module_id( USHORT family
)
77 if (family
== WS_AF_INET
) return &NPI_MS_IPV4_MODULEID
;
78 if (family
== WS_AF_INET6
) return &NPI_MS_IPV6_MODULEID
;
82 DWORD WINAPI
ConvertGuidToStringA( const GUID
*guid
, char *str
, DWORD len
)
84 if (len
< CHARS_IN_GUID
) return ERROR_INSUFFICIENT_BUFFER
;
85 sprintf( str
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
86 guid
->Data1
, guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2],
87 guid
->Data4
[3], guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7] );
91 DWORD WINAPI
ConvertGuidToStringW( const GUID
*guid
, WCHAR
*str
, DWORD len
)
93 static const WCHAR fmt
[] = { '{','%','0','8','X','-','%','0','4','X','-','%','0','4','X','-',
94 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X',
95 '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','}',0 };
97 if (len
< CHARS_IN_GUID
) return ERROR_INSUFFICIENT_BUFFER
;
99 guid
->Data1
, guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2],
100 guid
->Data4
[3], guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7] );
101 return ERROR_SUCCESS
;
104 DWORD WINAPI
ConvertStringToGuidW( const WCHAR
*str
, GUID
*guid
)
108 RtlInitUnicodeString( &ustr
, str
);
109 return RtlNtStatusToDosError( RtlGUIDFromString( &ustr
, guid
) );
112 static void if_counted_string_copy( WCHAR
*dst
, unsigned int len
, IF_COUNTED_STRING
*src
)
114 unsigned int copy
= src
->Length
;
116 if (copy
>= len
* sizeof(WCHAR
)) copy
= 0;
117 memcpy( dst
, src
->String
, copy
);
118 memset( (char *)dst
+ copy
, 0, len
* sizeof(WCHAR
) - copy
);
121 /******************************************************************
122 * AddIPAddress (IPHLPAPI.@)
124 * Add an IP address to an adapter.
127 * Address [In] IP address to add to the adapter
128 * IpMask [In] subnet mask for the IP address
129 * IfIndex [In] adapter index to add the address
130 * NTEContext [Out] Net Table Entry (NTE) context for the IP address
131 * NTEInstance [Out] NTE instance for the IP address
135 * Failure: error code from winerror.h
138 * Stub. Currently returns ERROR_NOT_SUPPORTED.
140 DWORD WINAPI
AddIPAddress(IPAddr Address
, IPMask IpMask
, DWORD IfIndex
, PULONG NTEContext
, PULONG NTEInstance
)
143 return ERROR_NOT_SUPPORTED
;
146 /******************************************************************
147 * CancelIPChangeNotify (IPHLPAPI.@)
149 * Cancel a previous notification created by NotifyAddrChange or
153 * overlapped [In] overlapped structure that notifies the caller
160 * Stub, returns FALSE.
162 BOOL WINAPI
CancelIPChangeNotify(LPOVERLAPPED overlapped
)
164 FIXME("(overlapped %p): stub\n", overlapped
);
169 /******************************************************************
170 * CancelMibChangeNotify2 (IPHLPAPI.@)
172 DWORD WINAPI
CancelMibChangeNotify2(HANDLE handle
)
174 FIXME("(handle %p): stub\n", handle
);
179 /******************************************************************
180 * CreateIpForwardEntry (IPHLPAPI.@)
182 * Create a route in the local computer's IP table.
185 * pRoute [In] new route information
189 * Failure: error code from winerror.h
192 * Stub, always returns NO_ERROR.
194 DWORD WINAPI
CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute
)
196 FIXME("(pRoute %p): stub\n", pRoute
);
197 /* could use SIOCADDRT, not sure I want to */
202 /******************************************************************
203 * CreateIpNetEntry (IPHLPAPI.@)
205 * Create entry in the ARP table.
208 * pArpEntry [In] new ARP entry
212 * Failure: error code from winerror.h
215 * Stub, always returns NO_ERROR.
217 DWORD WINAPI
CreateIpNetEntry(PMIB_IPNETROW pArpEntry
)
219 FIXME("(pArpEntry %p)\n", pArpEntry
);
220 /* could use SIOCSARP on systems that support it, not sure I want to */
225 /******************************************************************
226 * CreateProxyArpEntry (IPHLPAPI.@)
228 * Create a Proxy ARP (PARP) entry for an IP address.
231 * dwAddress [In] IP address for which this computer acts as a proxy.
232 * dwMask [In] subnet mask for dwAddress
233 * dwIfIndex [In] interface index
237 * Failure: error code from winerror.h
240 * Stub, returns ERROR_NOT_SUPPORTED.
242 DWORD WINAPI
CreateProxyArpEntry(DWORD dwAddress
, DWORD dwMask
, DWORD dwIfIndex
)
244 FIXME("(dwAddress 0x%08x, dwMask 0x%08x, dwIfIndex 0x%08x): stub\n",
245 dwAddress
, dwMask
, dwIfIndex
);
246 return ERROR_NOT_SUPPORTED
;
249 static char *debugstr_ipv6(const struct WS_sockaddr_in6
*sin
, char *buf
)
251 const IN6_ADDR
*addr
= &sin
->sin6_addr
;
254 BOOL in_zero
= FALSE
;
256 for (i
= 0; i
< 7; i
++)
258 if (!addr
->u
.Word
[i
])
270 p
+= sprintf(p
, "%x:", ntohs(addr
->u
.Word
[i
]));
274 sprintf(p
, "%x", ntohs(addr
->u
.Word
[7]));
278 static BOOL
map_address_6to4( const SOCKADDR_IN6
*addr6
, SOCKADDR_IN
*addr4
)
282 if (addr6
->sin6_family
!= WS_AF_INET6
) return FALSE
;
284 for (i
= 0; i
< 5; i
++)
285 if (addr6
->sin6_addr
.u
.Word
[i
]) return FALSE
;
287 if (addr6
->sin6_addr
.u
.Word
[5] != 0xffff) return FALSE
;
289 addr4
->sin_family
= WS_AF_INET
;
290 addr4
->sin_port
= addr6
->sin6_port
;
291 addr4
->sin_addr
.S_un
.S_addr
= addr6
->sin6_addr
.u
.Word
[6] << 16 | addr6
->sin6_addr
.u
.Word
[7];
292 memset( &addr4
->sin_zero
, 0, sizeof(addr4
->sin_zero
) );
297 static BOOL
find_src_address( MIB_IPADDRTABLE
*table
, const SOCKADDR_IN
*dst
, SOCKADDR_IN6
*src
)
299 MIB_IPFORWARDROW row
;
302 if (GetBestRoute( dst
->sin_addr
.S_un
.S_addr
, 0, &row
)) return FALSE
;
304 for (i
= 0; i
< table
->dwNumEntries
; i
++)
306 /* take the first address */
307 if (table
->table
[i
].dwIndex
== row
.dwForwardIfIndex
)
309 src
->sin6_family
= WS_AF_INET6
;
311 src
->sin6_flowinfo
= 0;
312 for (j
= 0; j
< 5; j
++) src
->sin6_addr
.u
.Word
[j
] = 0;
313 src
->sin6_addr
.u
.Word
[5] = 0xffff;
314 src
->sin6_addr
.u
.Word
[6] = table
->table
[i
].dwAddr
& 0xffff;
315 src
->sin6_addr
.u
.Word
[7] = table
->table
[i
].dwAddr
>> 16;
323 /******************************************************************
324 * CreateSortedAddressPairs (IPHLPAPI.@)
326 DWORD WINAPI
CreateSortedAddressPairs( const PSOCKADDR_IN6 src_list
, DWORD src_count
,
327 const PSOCKADDR_IN6 dst_list
, DWORD dst_count
,
328 DWORD options
, PSOCKADDR_IN6_PAIR
*pair_list
,
332 SOCKADDR_IN6_PAIR
*pairs
;
335 MIB_IPADDRTABLE
*table
;
337 FIXME( "(src_list %p src_count %u dst_list %p dst_count %u options %x pair_list %p pair_count %p): stub\n",
338 src_list
, src_count
, dst_list
, dst_count
, options
, pair_list
, pair_count
);
340 if (src_list
|| src_count
|| !dst_list
|| !pair_list
|| !pair_count
|| dst_count
> 500)
341 return ERROR_INVALID_PARAMETER
;
343 for (i
= 0; i
< dst_count
; i
++)
345 if (!map_address_6to4( &dst_list
[i
], &addr4
))
347 FIXME("only mapped IPv4 addresses are supported\n");
348 return ERROR_NOT_SUPPORTED
;
352 size
= dst_count
* sizeof(*pairs
);
353 size
+= dst_count
* sizeof(SOCKADDR_IN6
) * 2; /* source address + destination address */
354 if (!(pairs
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_NOT_ENOUGH_MEMORY
;
355 ptr
= (SOCKADDR_IN6
*)&pairs
[dst_count
];
357 if ((ret
= AllocateAndGetIpAddrTableFromStack( &table
, FALSE
, GetProcessHeap(), 0 )))
359 HeapFree( GetProcessHeap(), 0, pairs
);
363 for (i
= 0; i
< dst_count
; i
++)
365 pairs
[i
].SourceAddress
= ptr
++;
366 if (!map_address_6to4( &dst_list
[i
], &addr4
) ||
367 !find_src_address( table
, &addr4
, pairs
[i
].SourceAddress
))
370 FIXME( "source address for %s not found\n", debugstr_ipv6(&dst_list
[i
], buf
) );
371 memset( pairs
[i
].SourceAddress
, 0, sizeof(*pairs
[i
].SourceAddress
) );
372 pairs
[i
].SourceAddress
->sin6_family
= WS_AF_INET6
;
375 pairs
[i
].DestinationAddress
= ptr
++;
376 memcpy( pairs
[i
].DestinationAddress
, &dst_list
[i
], sizeof(*pairs
[i
].DestinationAddress
) );
379 *pair_count
= dst_count
;
381 HeapFree( GetProcessHeap(), 0, table
);
386 /******************************************************************
387 * DeleteIPAddress (IPHLPAPI.@)
389 * Delete an IP address added with AddIPAddress().
392 * NTEContext [In] NTE context from AddIPAddress();
396 * Failure: error code from winerror.h
399 * Stub, returns ERROR_NOT_SUPPORTED.
401 DWORD WINAPI
DeleteIPAddress(ULONG NTEContext
)
403 FIXME("(NTEContext %d): stub\n", NTEContext
);
404 return ERROR_NOT_SUPPORTED
;
408 /******************************************************************
409 * DeleteIpForwardEntry (IPHLPAPI.@)
414 * pRoute [In] route to delete
418 * Failure: error code from winerror.h
421 * Stub, returns NO_ERROR.
423 DWORD WINAPI
DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute
)
425 FIXME("(pRoute %p): stub\n", pRoute
);
426 /* could use SIOCDELRT, not sure I want to */
431 /******************************************************************
432 * DeleteIpNetEntry (IPHLPAPI.@)
434 * Delete an ARP entry.
437 * pArpEntry [In] ARP entry to delete
441 * Failure: error code from winerror.h
444 * Stub, returns NO_ERROR.
446 DWORD WINAPI
DeleteIpNetEntry(PMIB_IPNETROW pArpEntry
)
448 FIXME("(pArpEntry %p): stub\n", pArpEntry
);
449 /* could use SIOCDARP on systems that support it, not sure I want to */
454 /******************************************************************
455 * DeleteProxyArpEntry (IPHLPAPI.@)
457 * Delete a Proxy ARP entry.
460 * dwAddress [In] IP address for which this computer acts as a proxy.
461 * dwMask [In] subnet mask for dwAddress
462 * dwIfIndex [In] interface index
466 * Failure: error code from winerror.h
469 * Stub, returns ERROR_NOT_SUPPORTED.
471 DWORD WINAPI
DeleteProxyArpEntry(DWORD dwAddress
, DWORD dwMask
, DWORD dwIfIndex
)
473 FIXME("(dwAddress 0x%08x, dwMask 0x%08x, dwIfIndex 0x%08x): stub\n",
474 dwAddress
, dwMask
, dwIfIndex
);
475 return ERROR_NOT_SUPPORTED
;
479 /******************************************************************
480 * EnableRouter (IPHLPAPI.@)
482 * Turn on ip forwarding.
486 * pOverlapped [In/Out] hEvent member should contain a valid handle.
489 * Success: ERROR_IO_PENDING
490 * Failure: error code from winerror.h
493 * Stub, returns ERROR_NOT_SUPPORTED.
495 DWORD WINAPI
EnableRouter(HANDLE
* pHandle
, OVERLAPPED
* pOverlapped
)
497 FIXME("(pHandle %p, pOverlapped %p): stub\n", pHandle
, pOverlapped
);
498 /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
499 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
501 return ERROR_NOT_SUPPORTED
;
505 /******************************************************************
506 * FlushIpNetTable (IPHLPAPI.@)
508 * Delete all ARP entries of an interface
511 * dwIfIndex [In] interface index
515 * Failure: error code from winerror.h
518 * Stub, returns ERROR_NOT_SUPPORTED.
520 DWORD WINAPI
FlushIpNetTable(DWORD dwIfIndex
)
522 FIXME("(dwIfIndex 0x%08x): stub\n", dwIfIndex
);
523 /* this flushes the arp cache of the given index */
524 return ERROR_NOT_SUPPORTED
;
527 /******************************************************************
528 * FreeMibTable (IPHLPAPI.@)
530 * Free buffer allocated by network functions
533 * ptr [In] pointer to the buffer to free
536 void WINAPI
FreeMibTable(void *ptr
)
538 TRACE("(%p)\n", ptr
);
539 HeapFree(GetProcessHeap(), 0, ptr
);
542 /******************************************************************
543 * GetAdapterIndex (IPHLPAPI.@)
545 * Get interface index from its name.
548 * adapter_name [In] unicode string with the adapter name
549 * index [Out] returns found interface index
553 * Failure: error code from winerror.h
555 DWORD WINAPI
GetAdapterIndex( WCHAR
*adapter_name
, ULONG
*index
)
557 MIB_IFTABLE
*if_table
;
560 TRACE( "name %s, index %p\n", debugstr_w( adapter_name
), index
);
562 err
= AllocateAndGetIfTableFromStack( &if_table
, 0, GetProcessHeap(), 0 );
565 err
= ERROR_INVALID_PARAMETER
;
566 for (i
= 0; i
< if_table
->dwNumEntries
; i
++)
568 if (!strcmpW( adapter_name
, if_table
->table
[i
].wszName
))
570 *index
= if_table
->table
[i
].dwIndex
;
575 heap_free( if_table
);
579 static DWORD
get_wins_servers( SOCKADDR_INET
**servers
)
583 DWORD size
, i
, count
= 0;
584 static const char *values
[] = { "WinsServer", "BackupWinsServer" };
585 IN_ADDR addrs
[ARRAY_SIZE(values
)];
588 /* @@ Wine registry key: HKCU\Software\Wine\Network */
589 if (RegOpenKeyA( HKEY_CURRENT_USER
, "Software\\Wine\\Network", &key
)) return 0;
591 for (i
= 0; i
< ARRAY_SIZE(values
); i
++)
594 if (!RegQueryValueExA( key
, values
[i
], NULL
, NULL
, (LPBYTE
)buf
, &size
))
595 if (!RtlIpv4StringToAddressA( buf
, TRUE
, NULL
, addrs
+ count
) &&
596 addrs
[count
].WS_s_addr
!= INADDR_NONE
&& addrs
[count
].WS_s_addr
!= INADDR_ANY
)
603 *servers
= heap_alloc_zero( count
* sizeof(**servers
) );
604 if (!*servers
) return 0;
605 for (i
= 0; i
< count
; i
++)
607 (*servers
)[i
].Ipv4
.sin_family
= WS_AF_INET
;
608 (*servers
)[i
].Ipv4
.sin_addr
= addrs
[i
];
614 static void ip_addr_string_init( IP_ADDR_STRING
*s
, const IN_ADDR
*addr
, const IN_ADDR
*mask
, DWORD ctxt
)
618 if (addr
) RtlIpv4AddressToStringA( addr
, s
->IpAddress
.String
);
619 else s
->IpAddress
.String
[0] = '\0';
620 if (mask
) RtlIpv4AddressToStringA( mask
, s
->IpMask
.String
);
621 else s
->IpMask
.String
[0] = '\0';
625 /******************************************************************
626 * GetAdaptersInfo (IPHLPAPI.@)
628 * Get information about adapters.
631 * info [Out] buffer for adapter infos
632 * size [In] length of output buffer
634 DWORD WINAPI
GetAdaptersInfo( IP_ADAPTER_INFO
*info
, ULONG
*size
)
636 DWORD err
, if_count
, if_num
= 0, uni_count
, fwd_count
, needed
, wins_server_count
;
637 DWORD len
, i
, uni
, fwd
;
638 NET_LUID
*if_keys
= NULL
;
639 struct nsi_ndis_ifinfo_rw
*if_rw
= NULL
;
640 struct nsi_ndis_ifinfo_dynamic
*if_dyn
= NULL
;
641 struct nsi_ndis_ifinfo_static
*if_stat
= NULL
;
642 struct nsi_ipv4_unicast_key
*uni_keys
= NULL
;
643 struct nsi_ip_unicast_rw
*uni_rw
= NULL
;
644 struct nsi_ipv4_forward_key
*fwd_keys
= NULL
;
645 SOCKADDR_INET
*wins_servers
= NULL
;
646 IP_ADDR_STRING
*extra_ip_addrs
, *cursor
;
649 TRACE( "info %p, size %p\n", info
, size
);
650 if (!size
) return ERROR_INVALID_PARAMETER
;
652 err
= NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
,
653 (void **)&if_keys
, sizeof(*if_keys
), (void **)&if_rw
, sizeof(*if_rw
),
654 (void **)&if_dyn
, sizeof(*if_dyn
), (void **)&if_stat
, sizeof(*if_stat
), &if_count
, 0 );
656 for (i
= 0; i
< if_count
; i
++)
658 if (if_stat
[i
].type
== IF_TYPE_SOFTWARE_LOOPBACK
) continue;
668 err
= NsiAllocateAndGetTable( 1, &NPI_MS_IPV4_MODULEID
, NSI_IP_UNICAST_TABLE
,
669 (void **)&uni_keys
, sizeof(*uni_keys
), (void **)&uni_rw
, sizeof(*uni_rw
),
670 NULL
, 0, NULL
, 0, &uni_count
, 0 );
673 /* Slightly overestimate the needed size by assuming that all
674 unicast addresses require a separate IP_ADDR_STRING. */
676 needed
= if_num
* sizeof(*info
) + uni_count
* sizeof(IP_ADDR_STRING
);
677 if (!info
|| *size
< needed
)
680 err
= ERROR_BUFFER_OVERFLOW
;
684 err
= NsiAllocateAndGetTable( 1, &NPI_MS_IPV4_MODULEID
, NSI_IP_FORWARD_TABLE
,
685 (void **)&fwd_keys
, sizeof(*fwd_keys
), NULL
, 0,
686 NULL
, 0, NULL
, 0, &fwd_count
, 0 );
689 wins_server_count
= get_wins_servers( &wins_servers
);
691 extra_ip_addrs
= (IP_ADDR_STRING
*)(info
+ if_num
);
692 for (i
= 0; i
< if_count
; i
++)
694 if (if_stat
[i
].type
== IF_TYPE_SOFTWARE_LOOPBACK
) continue;
696 info
->Next
= info
+ 1;
697 info
->ComboIndex
= 0;
698 ConvertGuidToStringA( &if_stat
[i
].if_guid
, info
->AdapterName
, sizeof(info
->AdapterName
) );
699 len
= WideCharToMultiByte( CP_ACP
, 0, if_stat
[i
].descr
.String
, if_stat
[i
].descr
.Length
/ sizeof(WCHAR
),
700 info
->Description
, sizeof(info
->Description
) - 1, NULL
, NULL
);
701 info
->Description
[len
] = '\0';
702 info
->AddressLength
= if_rw
[i
].phys_addr
.Length
;
703 if (info
->AddressLength
> sizeof(info
->Address
)) info
->AddressLength
= 0;
704 memcpy( info
->Address
, if_rw
[i
].phys_addr
.Address
, info
->AddressLength
);
705 memset( info
->Address
+ info
->AddressLength
, 0, sizeof(info
->Address
) - info
->AddressLength
);
706 info
->Index
= if_stat
[i
].if_index
;
707 info
->Type
= if_stat
[i
].type
;
708 info
->DhcpEnabled
= TRUE
; /* FIXME */
709 info
->CurrentIpAddress
= NULL
;
712 for (uni
= 0; uni
< uni_count
; uni
++)
714 if (uni_keys
[uni
].luid
.Value
!= if_keys
[i
].Value
) continue;
715 if (!cursor
) cursor
= &info
->IpAddressList
;
718 cursor
->Next
= extra_ip_addrs
++;
719 cursor
= cursor
->Next
;
721 ConvertLengthToIpv4Mask( uni_rw
[uni
].on_link_prefix
, &mask
.WS_s_addr
);
722 ip_addr_string_init( cursor
, &uni_keys
[uni
].addr
, &mask
, 0 );
726 mask
.WS_s_addr
= INADDR_ANY
;
727 ip_addr_string_init( &info
->IpAddressList
, &mask
, &mask
, 0 );
730 gw
.WS_s_addr
= INADDR_ANY
;
731 mask
.WS_s_addr
= INADDR_NONE
;
732 for (fwd
= 0; fwd
< fwd_count
; fwd
++)
733 { /* find the first router on this interface */
734 if (fwd_keys
[fwd
].luid
.Value
== if_keys
[i
].Value
&&
735 fwd_keys
[fwd
].next_hop
.WS_s_addr
!= INADDR_ANY
&&
736 !fwd_keys
[fwd
].prefix_len
)
738 gw
= fwd_keys
[fwd
].next_hop
;
742 ip_addr_string_init( &info
->GatewayList
, &gw
, &mask
, 0 );
744 ip_addr_string_init( &info
->DhcpServer
, NULL
, NULL
, 0 );
746 info
->HaveWins
= !!wins_server_count
;
747 ip_addr_string_init( &info
->PrimaryWinsServer
, NULL
, NULL
, 0 );
748 ip_addr_string_init( &info
->SecondaryWinsServer
, NULL
, NULL
, 0 );
751 mask
.WS_s_addr
= INADDR_NONE
;
752 ip_addr_string_init( &info
->PrimaryWinsServer
, &wins_servers
[0].Ipv4
.sin_addr
, &mask
, 0 );
753 if (wins_server_count
> 1)
754 ip_addr_string_init( &info
->SecondaryWinsServer
, &wins_servers
[1].Ipv4
.sin_addr
, &mask
, 0 );
757 info
->LeaseObtained
= 0;
758 info
->LeaseExpires
= 0;
762 info
[-1].Next
= NULL
;
765 heap_free( wins_servers
);
766 NsiFreeTable( fwd_keys
, NULL
, NULL
, NULL
);
767 NsiFreeTable( uni_keys
, uni_rw
, NULL
, NULL
);
768 NsiFreeTable( if_keys
, if_rw
, if_dyn
, if_stat
);
772 static void address_entry_free( void *ptr
, ULONG offset
, void *ctxt
)
777 static void address_entry_size( void *ptr
, ULONG offset
, void *ctxt
)
779 IP_ADAPTER_DNS_SERVER_ADDRESS
*src_addr
= ptr
; /* all list types are super-sets of this type */
780 ULONG
*total
= (ULONG
*)ctxt
, align
= sizeof(ULONGLONG
) - 1;
782 *total
= (*total
+ src_addr
->u
.s
.Length
+ src_addr
->Address
.iSockaddrLength
+ align
) & ~align
;
785 struct address_entry_copy_params
787 IP_ADAPTER_ADDRESSES
*src
, *dst
;
793 static void address_entry_copy( void *ptr
, ULONG offset
, void *ctxt
)
795 struct address_entry_copy_params
*params
= ctxt
;
796 IP_ADAPTER_DNS_SERVER_ADDRESS
*src_addr
= ptr
; /* all list types are super-sets of this type */
797 IP_ADAPTER_DNS_SERVER_ADDRESS
*dst_addr
= (IP_ADAPTER_DNS_SERVER_ADDRESS
*)params
->ptr
;
798 ULONG align
= sizeof(ULONGLONG
) - 1;
800 memcpy( dst_addr
, src_addr
, src_addr
->u
.s
.Length
);
801 params
->ptr
+= src_addr
->u
.s
.Length
;
802 dst_addr
->Address
.lpSockaddr
= (SOCKADDR
*)params
->ptr
;
803 memcpy( dst_addr
->Address
.lpSockaddr
, src_addr
->Address
.lpSockaddr
, src_addr
->Address
.iSockaddrLength
);
804 params
->ptr
+= (src_addr
->Address
.iSockaddrLength
+ align
) & ~align
;
806 if (params
->cur_offset
!= offset
) /* new list */
808 params
->next
= (BYTE
*)params
->dst
+ offset
;
809 params
->cur_offset
= offset
;
811 *(IP_ADAPTER_DNS_SERVER_ADDRESS
**)params
->next
= dst_addr
;
812 params
->next
= &dst_addr
->Next
;
815 static void address_lists_iterate( IP_ADAPTER_ADDRESSES
*aa
, void (*fn
)(void *entry
, ULONG offset
, void *ctxt
), void *ctxt
)
817 IP_ADAPTER_UNICAST_ADDRESS
*uni
;
818 IP_ADAPTER_DNS_SERVER_ADDRESS
*dns
;
819 IP_ADAPTER_GATEWAY_ADDRESS
*gw
;
820 IP_ADAPTER_PREFIX
*prefix
;
823 for (uni
= aa
->FirstUnicastAddress
; uni
; uni
= next
)
826 fn( uni
, FIELD_OFFSET( IP_ADAPTER_ADDRESSES
, FirstUnicastAddress
), ctxt
);
829 for (dns
= aa
->FirstDnsServerAddress
; dns
; dns
= next
)
832 fn( dns
, FIELD_OFFSET( IP_ADAPTER_ADDRESSES
, FirstDnsServerAddress
), ctxt
);
835 for (gw
= aa
->FirstGatewayAddress
; gw
; gw
= next
)
838 fn( gw
, FIELD_OFFSET( IP_ADAPTER_ADDRESSES
, FirstGatewayAddress
), ctxt
);
841 for (prefix
= aa
->FirstPrefix
; prefix
; prefix
= next
)
844 fn( prefix
, FIELD_OFFSET( IP_ADAPTER_ADDRESSES
, FirstPrefix
), ctxt
);
848 void adapters_addresses_free( IP_ADAPTER_ADDRESSES
*info
)
850 IP_ADAPTER_ADDRESSES
*aa
;
852 for (aa
= info
; aa
; aa
= aa
->Next
)
854 address_lists_iterate( aa
, address_entry_free
, NULL
);
856 heap_free( aa
->DnsSuffix
);
861 ULONG
adapters_addresses_size( IP_ADAPTER_ADDRESSES
*info
)
863 IP_ADAPTER_ADDRESSES
*aa
;
864 ULONG size
= 0, align
= sizeof(ULONGLONG
) - 1;
866 for (aa
= info
; aa
; aa
= aa
->Next
)
868 size
+= sizeof(*aa
) + ((strlen( aa
->AdapterName
) + 1 + 1) & ~1);
869 size
+= (strlenW( aa
->Description
) + 1 + strlenW( aa
->DnsSuffix
) + 1) * sizeof(WCHAR
);
870 if (aa
->FriendlyName
) size
+= (strlenW(aa
->FriendlyName
) + 1) * sizeof(WCHAR
);
871 size
= (size
+ align
) & ~align
;
872 address_lists_iterate( aa
, address_entry_size
, &size
);
877 void adapters_addresses_copy( IP_ADAPTER_ADDRESSES
*dst
, IP_ADAPTER_ADDRESSES
*src
)
880 DWORD len
, align
= sizeof(ULONGLONG
) - 1;
881 struct address_entry_copy_params params
;
885 ptr
= (char *)(dst
+ 1);
887 dst
->AdapterName
= ptr
;
888 len
= strlen( src
->AdapterName
) + 1;
889 memcpy( dst
->AdapterName
, src
->AdapterName
, len
);
890 ptr
+= (len
+ 1) & ~1;
891 dst
->Description
= (WCHAR
*)ptr
;
892 len
= (strlenW( src
->Description
) + 1) * sizeof(WCHAR
);
893 memcpy( dst
->Description
, src
->Description
, len
);
895 dst
->DnsSuffix
= (WCHAR
*)ptr
;
896 len
= (strlenW( src
->DnsSuffix
) + 1) * sizeof(WCHAR
);
897 memcpy( dst
->DnsSuffix
, src
->DnsSuffix
, len
);
899 if (src
->FriendlyName
)
901 dst
->FriendlyName
= (WCHAR
*)ptr
;
902 len
= (strlenW( src
->FriendlyName
) + 1) * sizeof(WCHAR
);
903 memcpy( dst
->FriendlyName
, src
->FriendlyName
, len
);
906 ptr
= (char *)(((UINT_PTR
)ptr
+ align
) & ~align
);
912 params
.cur_offset
= ~0u;
913 address_lists_iterate( src
, address_entry_copy
, ¶ms
);
918 dst
->Next
= (IP_ADAPTER_ADDRESSES
*)ptr
;
925 static BOOL
sockaddr_is_loopback( SOCKADDR
*sock
)
927 if (sock
->sa_family
== WS_AF_INET
)
929 SOCKADDR_IN
*sin
= (SOCKADDR_IN
*)sock
;
930 return (sin
->sin_addr
.WS_s_addr
& 0xff) == 127;
932 else if (sock
->sa_family
== WS_AF_INET6
)
934 SOCKADDR_IN6
*sin6
= (SOCKADDR_IN6
*)sock
;
935 return WS_IN6_IS_ADDR_LOOPBACK( &sin6
->sin6_addr
);
940 static BOOL
sockaddr_is_linklocal( SOCKADDR
*sock
)
942 if (sock
->sa_family
== WS_AF_INET6
)
944 SOCKADDR_IN6
*sin6
= (SOCKADDR_IN6
*)sock
;
945 return WS_IN6_IS_ADDR_LINKLOCAL( &sin6
->sin6_addr
);
950 static BOOL
unicast_is_dns_eligible( IP_ADAPTER_UNICAST_ADDRESS
*uni
)
952 return !sockaddr_is_loopback( uni
->Address
.lpSockaddr
) &&
953 !sockaddr_is_linklocal( uni
->Address
.lpSockaddr
);
956 static DWORD
unicast_addresses_alloc( IP_ADAPTER_ADDRESSES
*aa
, ULONG family
, ULONG flags
)
958 struct nsi_ipv4_unicast_key
*key4
;
959 struct nsi_ipv6_unicast_key
*key6
;
960 struct nsi_ip_unicast_rw
*rw
;
961 struct nsi_ip_unicast_dynamic
*dyn
;
962 struct nsi_ip_unicast_static
*stat
;
963 IP_ADAPTER_UNICAST_ADDRESS
*addr
, **next
;
964 DWORD err
, count
, i
, key_size
= (family
== WS_AF_INET
) ? sizeof(*key4
) : sizeof(*key6
);
965 DWORD sockaddr_size
= (family
== WS_AF_INET
) ? sizeof(SOCKADDR_IN
) : sizeof(SOCKADDR_IN6
);
969 err
= NsiAllocateAndGetTable( 1, ip_module_id( family
), NSI_IP_UNICAST_TABLE
, &key
, key_size
,
970 (void **)&rw
, sizeof(*rw
), (void **)&dyn
, sizeof(*dyn
),
971 (void **)&stat
, sizeof(*stat
), &count
, 0 );
977 for (next
= &aa
->FirstUnicastAddress
; *next
; next
= &(*next
)->Next
)
980 for (i
= 0; i
< count
; i
++)
982 key4
= (struct nsi_ipv4_unicast_key
*)key
+ i
;
983 key6
= (struct nsi_ipv6_unicast_key
*)key
+ i
;
984 luid
= (family
== WS_AF_INET
) ? &key4
->luid
: &key6
->luid
;
985 if (luid
->Value
!= aa
->Luid
.Value
) continue;
986 addr
= heap_alloc_zero( sizeof(*addr
) + sockaddr_size
);
989 err
= ERROR_NOT_ENOUGH_MEMORY
;
992 addr
->u
.s
.Length
= sizeof(*addr
);
993 addr
->Address
.lpSockaddr
= (SOCKADDR
*)(addr
+ 1);
994 addr
->Address
.iSockaddrLength
= sockaddr_size
;
995 addr
->Address
.lpSockaddr
->sa_family
= family
;
996 if (family
== WS_AF_INET
)
998 SOCKADDR_IN
*in
= (SOCKADDR_IN
*)addr
->Address
.lpSockaddr
;
999 in
->sin_addr
= key4
->addr
;
1003 SOCKADDR_IN6
*in6
= (SOCKADDR_IN6
*)addr
->Address
.lpSockaddr
;
1004 in6
->sin6_addr
= key6
->addr
;
1005 in6
->sin6_scope_id
= dyn
[i
].scope_id
;
1007 addr
->PrefixOrigin
= rw
[i
].prefix_origin
;
1008 addr
->SuffixOrigin
= rw
[i
].suffix_origin
;
1009 addr
->DadState
= dyn
[i
].dad_state
;
1010 addr
->ValidLifetime
= rw
[i
].valid_lifetime
;
1011 addr
->PreferredLifetime
= rw
[i
].preferred_lifetime
;
1012 addr
->LeaseLifetime
= rw
[i
].valid_lifetime
; /* FIXME */
1013 addr
->OnLinkPrefixLength
= rw
[i
].on_link_prefix
;
1014 if (unicast_is_dns_eligible( addr
)) addr
->u
.s
.Flags
|= IP_ADAPTER_ADDRESS_DNS_ELIGIBLE
;
1023 NsiFreeTable( key
, rw
, dyn
, stat
);
1027 static DWORD
gateway_and_prefix_addresses_alloc( IP_ADAPTER_ADDRESSES
*aa
, ULONG family
, ULONG flags
)
1029 struct nsi_ipv4_forward_key
*key4
;
1030 struct nsi_ipv6_forward_key
*key6
;
1031 IP_ADAPTER_GATEWAY_ADDRESS
*gw
, **gw_next
;
1032 IP_ADAPTER_PREFIX
*prefix
, **prefix_next
;
1033 DWORD err
, count
, i
, prefix_len
, key_size
= (family
== WS_AF_INET
) ? sizeof(*key4
) : sizeof(*key6
);
1034 DWORD sockaddr_size
= (family
== WS_AF_INET
) ? sizeof(SOCKADDR_IN
) : sizeof(SOCKADDR_IN6
);
1035 SOCKADDR_INET sockaddr
;
1039 err
= NsiAllocateAndGetTable( 1, ip_module_id( family
), NSI_IP_FORWARD_TABLE
, &key
, key_size
,
1040 NULL
, 0, NULL
, 0, NULL
, 0, &count
, 0 );
1041 if (err
) return err
;
1045 for (gw_next
= &aa
->FirstGatewayAddress
; *gw_next
; gw_next
= &(*gw_next
)->Next
)
1047 for (prefix_next
= &aa
->FirstPrefix
; *prefix_next
; prefix_next
= &(*prefix_next
)->Next
)
1050 for (i
= 0; i
< count
; i
++)
1052 key4
= (struct nsi_ipv4_forward_key
*)key
+ i
;
1053 key6
= (struct nsi_ipv6_forward_key
*)key
+ i
;
1054 luid
= (family
== WS_AF_INET
) ? &key4
->luid
: &key6
->luid
;
1055 if (luid
->Value
!= aa
->Luid
.Value
) continue;
1057 if (flags
& GAA_FLAG_INCLUDE_ALL_GATEWAYS
)
1059 memset( &sockaddr
, 0, sizeof(sockaddr
) );
1060 if (family
== WS_AF_INET
)
1062 if (key4
->next_hop
.WS_s_addr
!= 0)
1064 sockaddr
.si_family
= family
;
1065 sockaddr
.Ipv4
.sin_addr
= key4
->next_hop
;
1070 static const IN6_ADDR zero
;
1071 if (memcmp( &key6
->next_hop
, &zero
, sizeof(zero
) ))
1073 sockaddr
.si_family
= family
;
1074 sockaddr
.Ipv6
.sin6_addr
= key6
->next_hop
;
1078 if (sockaddr
.si_family
)
1080 gw
= heap_alloc_zero( sizeof(*gw
) + sockaddr_size
);
1083 err
= ERROR_NOT_ENOUGH_MEMORY
;
1086 gw
->u
.s
.Length
= sizeof(*gw
);
1087 gw
->Address
.lpSockaddr
= (SOCKADDR
*)(gw
+ 1);
1088 gw
->Address
.iSockaddrLength
= sockaddr_size
;
1089 memcpy( gw
->Address
.lpSockaddr
, &sockaddr
, sockaddr_size
);
1091 gw_next
= &gw
->Next
;
1095 if (flags
& GAA_FLAG_INCLUDE_PREFIX
)
1097 memset( &sockaddr
, 0, sizeof(sockaddr
) );
1098 if (family
== WS_AF_INET
)
1100 if (!key4
->next_hop
.WS_s_addr
)
1102 sockaddr
.si_family
= family
;
1103 sockaddr
.Ipv4
.sin_addr
= key4
->prefix
;
1104 prefix_len
= key4
->prefix_len
;
1109 static const IN6_ADDR zero
;
1110 if (!memcmp( &key6
->next_hop
, &zero
, sizeof(zero
) ))
1112 sockaddr
.si_family
= family
;
1113 sockaddr
.Ipv6
.sin6_addr
= key6
->prefix
;
1114 prefix_len
= key6
->prefix_len
;
1118 if (sockaddr
.si_family
)
1120 prefix
= heap_alloc_zero( sizeof(*prefix
) + sockaddr_size
);
1123 err
= ERROR_NOT_ENOUGH_MEMORY
;
1126 prefix
->u
.s
.Length
= sizeof(*prefix
);
1127 prefix
->Address
.lpSockaddr
= (SOCKADDR
*)(prefix
+ 1);
1128 prefix
->Address
.iSockaddrLength
= sockaddr_size
;
1129 memcpy( prefix
->Address
.lpSockaddr
, &sockaddr
, sockaddr_size
);
1130 prefix
->PrefixLength
= prefix_len
;
1131 *prefix_next
= prefix
;
1132 prefix_next
= &prefix
->Next
;
1140 NsiFreeTable( key
, NULL
, NULL
, NULL
);
1144 static DWORD
call_families( DWORD (*fn
)( IP_ADAPTER_ADDRESSES
*aa
, ULONG family
, ULONG flags
),
1145 IP_ADAPTER_ADDRESSES
*aa
, ULONG family
, ULONG flags
)
1149 if (family
!= WS_AF_INET
)
1151 err
= fn( aa
, WS_AF_INET6
, flags
);
1152 if (err
) return err
;
1155 if (family
!= WS_AF_INET6
)
1157 err
= fn( aa
, WS_AF_INET
, flags
);
1158 if (err
) return err
;
1163 static DWORD
dns_servers_query_code( ULONG family
)
1165 if (family
== WS_AF_INET
) return DnsConfigDnsServersIpv4
;
1166 if (family
== WS_AF_INET6
) return DnsConfigDnsServersIpv6
;
1167 return DnsConfigDnsServersUnspec
;
1170 static DWORD
dns_info_alloc( IP_ADAPTER_ADDRESSES
*aa
, ULONG family
, ULONG flags
)
1172 char buf
[FIELD_OFFSET(DNS_ADDR_ARRAY
, AddrArray
[3])];
1173 IP_ADAPTER_DNS_SERVER_ADDRESS
*dns
, **next
;
1174 DWORD query
= dns_servers_query_code( family
);
1175 DWORD err
, i
, size
, attempt
, sockaddr_len
;
1176 WCHAR name
[MAX_ADAPTER_NAME_LENGTH
+ 1];
1177 DNS_ADDR_ARRAY
*servers
;
1178 DNS_TXT_DATAW
*search
;
1182 MultiByteToWideChar( CP_ACP
, 0, aa
->AdapterName
, -1, name
, ARRAY_SIZE(name
) );
1183 if (!(flags
& GAA_FLAG_SKIP_DNS_SERVER
))
1185 servers
= (DNS_ADDR_ARRAY
*)buf
;
1186 for (attempt
= 0; attempt
< 5; attempt
++)
1188 err
= DnsQueryConfig( query
, 0, name
, NULL
, servers
, &size
);
1189 if (err
!= ERROR_MORE_DATA
) break;
1190 if (servers
!= (DNS_ADDR_ARRAY
*)buf
) heap_free( servers
);
1191 servers
= heap_alloc( size
);
1194 err
= ERROR_NOT_ENOUGH_MEMORY
;
1200 next
= &aa
->FirstDnsServerAddress
;
1201 for (i
= 0; i
< servers
->AddrCount
; i
++)
1203 sockaddr_len
= servers
->AddrArray
[i
].Data
.DnsAddrUserDword
[0];
1204 if (sockaddr_len
> sizeof(servers
->AddrArray
[i
].MaxSa
))
1205 sockaddr_len
= sizeof(servers
->AddrArray
[i
].MaxSa
);
1206 dns
= heap_alloc_zero( sizeof(*dns
) + sockaddr_len
);
1209 err
= ERROR_NOT_ENOUGH_MEMORY
;
1212 dns
->u
.s
.Length
= sizeof(*dns
);
1213 dns
->Address
.lpSockaddr
= (SOCKADDR
*)(dns
+ 1);
1214 dns
->Address
.iSockaddrLength
= sockaddr_len
;
1215 memcpy( dns
->Address
.lpSockaddr
, servers
->AddrArray
[i
].MaxSa
, sockaddr_len
);
1220 if (servers
!= (DNS_ADDR_ARRAY
*)buf
) heap_free( servers
);
1224 aa
->DnsSuffix
= heap_alloc( MAX_DNS_SUFFIX_STRING_LENGTH
* sizeof(WCHAR
) );
1227 err
= ERROR_NOT_ENOUGH_MEMORY
;
1230 aa
->DnsSuffix
[0] = '\0';
1232 if (!DnsQueryConfig( DnsConfigSearchList
, 0, name
, NULL
, NULL
, &size
) &&
1233 (search
= heap_alloc( size
)))
1235 if (!DnsQueryConfig( DnsConfigSearchList
, 0, name
, NULL
, search
, &size
) &&
1236 search
->dwStringCount
&& strlenW( search
->pStringArray
[0] ) < MAX_DNS_SUFFIX_STRING_LENGTH
)
1238 strcpyW( aa
->DnsSuffix
, search
->pStringArray
[0] );
1240 heap_free( search
);
1250 static DWORD
adapters_addresses_alloc( ULONG family
, ULONG flags
, IP_ADAPTER_ADDRESSES
**info
)
1252 IP_ADAPTER_ADDRESSES
*aa
;
1254 struct nsi_ndis_ifinfo_rw
*rw
;
1255 struct nsi_ndis_ifinfo_dynamic
*dyn
;
1256 struct nsi_ndis_ifinfo_static
*stat
;
1257 DWORD err
, i
, count
, needed
;
1261 err
= NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, (void **)&luids
, sizeof(*luids
),
1262 (void **)&rw
, sizeof(*rw
), (void **)&dyn
, sizeof(*dyn
),
1263 (void **)&stat
, sizeof(*stat
), &count
, 0 );
1264 if (err
) return err
;
1266 needed
= count
* (sizeof(*aa
) + ((CHARS_IN_GUID
+ 1) & ~1) + sizeof(stat
->descr
.String
));
1267 if (!(flags
& GAA_FLAG_SKIP_FRIENDLY_NAME
)) needed
+= count
* sizeof(rw
->alias
.String
);
1269 aa
= heap_alloc_zero( needed
);
1272 err
= ERROR_NOT_ENOUGH_MEMORY
;
1276 str_ptr
= (char *)(aa
+ count
);
1277 for (i
= 0; i
< count
; i
++)
1279 aa
[i
].u
.s
.Length
= sizeof(*aa
);
1280 aa
[i
].u
.s
.IfIndex
= stat
[i
].if_index
;
1281 if (i
< count
- 1) aa
[i
].Next
= aa
+ i
+ 1;
1282 ConvertInterfaceLuidToGuid( luids
+ i
, &guid
);
1283 ConvertGuidToStringA( &guid
, str_ptr
, CHARS_IN_GUID
);
1284 aa
[i
].AdapterName
= str_ptr
;
1285 str_ptr
+= (CHARS_IN_GUID
+ 1) & ~1;
1286 if_counted_string_copy( (WCHAR
*)str_ptr
, ARRAY_SIZE(stat
[i
].descr
.String
), &stat
[i
].descr
);
1287 aa
[i
].Description
= (WCHAR
*)str_ptr
;
1288 str_ptr
+= sizeof(stat
[i
].descr
.String
);
1289 if (!(flags
& GAA_FLAG_SKIP_FRIENDLY_NAME
))
1291 if_counted_string_copy( (WCHAR
*)str_ptr
, ARRAY_SIZE(rw
[i
].alias
.String
), &rw
[i
].alias
);
1292 aa
[i
].FriendlyName
= (WCHAR
*)str_ptr
;
1293 str_ptr
+= sizeof(rw
[i
].alias
.String
);
1295 aa
[i
].PhysicalAddressLength
= rw
->phys_addr
.Length
;
1296 if (aa
[i
].PhysicalAddressLength
> sizeof(aa
[i
].PhysicalAddress
)) aa
[i
].PhysicalAddressLength
= 0;
1297 memcpy( aa
[i
].PhysicalAddress
, rw
->phys_addr
.Address
, aa
[i
].PhysicalAddressLength
);
1298 aa
[i
].Mtu
= dyn
[i
].mtu
;
1299 aa
[i
].IfType
= stat
[i
].type
;
1300 aa
[i
].OperStatus
= dyn
[i
].oper_status
;
1301 aa
[i
].TransmitLinkSpeed
= dyn
[i
].xmit_speed
;
1302 aa
[i
].ReceiveLinkSpeed
= dyn
[i
].rcv_speed
;
1303 aa
[i
].Luid
= luids
[i
];
1304 aa
[i
].NetworkGuid
= rw
[i
].network_guid
;
1305 aa
[i
].ConnectionType
= stat
[i
].conn_type
;
1308 if (!(flags
& GAA_FLAG_SKIP_UNICAST
))
1310 err
= call_families( unicast_addresses_alloc
, aa
, family
, flags
);
1314 if (flags
& (GAA_FLAG_INCLUDE_ALL_GATEWAYS
| GAA_FLAG_INCLUDE_PREFIX
))
1316 err
= call_families( gateway_and_prefix_addresses_alloc
, aa
, family
, flags
);
1320 err
= dns_info_alloc( aa
, family
, flags
);
1324 NsiFreeTable( luids
, rw
, dyn
, stat
);
1325 if (!err
) *info
= aa
;
1326 else adapters_addresses_free( aa
);
1330 ULONG WINAPI DECLSPEC_HOTPATCH
GetAdaptersAddresses( ULONG family
, ULONG flags
, void *reserved
,
1331 IP_ADAPTER_ADDRESSES
*aa
, ULONG
*size
)
1333 IP_ADAPTER_ADDRESSES
*info
;
1336 TRACE( "(%d, %08x, %p, %p, %p)\n", family
, flags
, reserved
, aa
, size
);
1338 if (!size
) return ERROR_INVALID_PARAMETER
;
1340 err
= adapters_addresses_alloc( family
, flags
, &info
);
1341 if (err
) return err
;
1343 needed
= adapters_addresses_size( info
);
1344 if (!aa
|| *size
< needed
)
1347 err
= ERROR_BUFFER_OVERFLOW
;
1350 adapters_addresses_copy( aa
, info
);
1352 adapters_addresses_free( info
);
1356 /******************************************************************
1357 * GetBestInterface (IPHLPAPI.@)
1359 * Get the interface, with the best route for the given IP address.
1362 * dwDestAddr [In] IP address to search the interface for
1363 * pdwBestIfIndex [Out] found best interface
1367 * Failure: error code from winerror.h
1369 DWORD WINAPI
GetBestInterface(IPAddr dwDestAddr
, PDWORD pdwBestIfIndex
)
1371 struct WS_sockaddr_in sa_in
;
1372 memset(&sa_in
, 0, sizeof(sa_in
));
1373 sa_in
.sin_family
= WS_AF_INET
;
1374 sa_in
.sin_addr
.S_un
.S_addr
= dwDestAddr
;
1375 return GetBestInterfaceEx((struct WS_sockaddr
*)&sa_in
, pdwBestIfIndex
);
1378 /******************************************************************
1379 * GetBestInterfaceEx (IPHLPAPI.@)
1381 * Get the interface, with the best route for the given IP address.
1384 * dwDestAddr [In] IP address to search the interface for
1385 * pdwBestIfIndex [Out] found best interface
1389 * Failure: error code from winerror.h
1391 DWORD WINAPI
GetBestInterfaceEx(struct WS_sockaddr
*pDestAddr
, PDWORD pdwBestIfIndex
)
1395 TRACE("pDestAddr %p, pdwBestIfIndex %p\n", pDestAddr
, pdwBestIfIndex
);
1396 if (!pDestAddr
|| !pdwBestIfIndex
)
1397 ret
= ERROR_INVALID_PARAMETER
;
1399 MIB_IPFORWARDROW ipRow
;
1401 if (pDestAddr
->sa_family
== WS_AF_INET
) {
1402 ret
= GetBestRoute(((struct WS_sockaddr_in
*)pDestAddr
)->sin_addr
.S_un
.S_addr
, 0, &ipRow
);
1403 if (ret
== ERROR_SUCCESS
)
1404 *pdwBestIfIndex
= ipRow
.dwForwardIfIndex
;
1406 FIXME("address family %d not supported\n", pDestAddr
->sa_family
);
1407 ret
= ERROR_NOT_SUPPORTED
;
1410 TRACE("returning %d\n", ret
);
1415 /******************************************************************
1416 * GetBestRoute (IPHLPAPI.@)
1418 * Get the best route for the given IP address.
1421 * dwDestAddr [In] IP address to search the best route for
1422 * dwSourceAddr [In] optional source IP address
1423 * pBestRoute [Out] found best route
1427 * Failure: error code from winerror.h
1429 DWORD WINAPI
GetBestRoute(DWORD dwDestAddr
, DWORD dwSourceAddr
, PMIB_IPFORWARDROW pBestRoute
)
1431 PMIB_IPFORWARDTABLE table
;
1434 TRACE("dwDestAddr 0x%08x, dwSourceAddr 0x%08x, pBestRoute %p\n", dwDestAddr
,
1435 dwSourceAddr
, pBestRoute
);
1437 return ERROR_INVALID_PARAMETER
;
1439 ret
= AllocateAndGetIpForwardTableFromStack(&table
, FALSE
, GetProcessHeap(), 0);
1441 DWORD ndx
, matchedBits
, matchedNdx
= table
->dwNumEntries
;
1443 for (ndx
= 0, matchedBits
= 0; ndx
< table
->dwNumEntries
; ndx
++) {
1444 if (table
->table
[ndx
].u1
.ForwardType
!= MIB_IPROUTE_TYPE_INVALID
&&
1445 (dwDestAddr
& table
->table
[ndx
].dwForwardMask
) ==
1446 (table
->table
[ndx
].dwForwardDest
& table
->table
[ndx
].dwForwardMask
)) {
1447 DWORD numShifts
, mask
;
1449 for (numShifts
= 0, mask
= table
->table
[ndx
].dwForwardMask
;
1450 mask
&& mask
& 1; mask
>>= 1, numShifts
++)
1452 if (numShifts
> matchedBits
) {
1453 matchedBits
= numShifts
;
1456 else if (!matchedBits
) {
1461 if (matchedNdx
< table
->dwNumEntries
) {
1462 memcpy(pBestRoute
, &table
->table
[matchedNdx
], sizeof(MIB_IPFORWARDROW
));
1463 ret
= ERROR_SUCCESS
;
1466 /* No route matches, which can happen if there's no default route. */
1467 ret
= ERROR_HOST_UNREACHABLE
;
1469 HeapFree(GetProcessHeap(), 0, table
);
1471 TRACE("returning %d\n", ret
);
1476 /******************************************************************
1477 * GetFriendlyIfIndex (IPHLPAPI.@)
1479 * Get a "friendly" version of IfIndex, which is one that doesn't
1480 * have the top byte set. Doesn't validate whether IfIndex is a valid
1484 * IfIndex [In] interface index to get the friendly one for
1487 * A friendly version of IfIndex.
1489 DWORD WINAPI
GetFriendlyIfIndex(DWORD IfIndex
)
1491 /* windows doesn't validate these, either, just makes sure the top byte is
1492 cleared. I assume my ifenum module never gives an index with the top
1494 TRACE("returning %d\n", IfIndex
);
1498 static void if_row_fill( MIB_IFROW
*row
, struct nsi_ndis_ifinfo_rw
*rw
, struct nsi_ndis_ifinfo_dynamic
*dyn
,
1499 struct nsi_ndis_ifinfo_static
*stat
)
1501 static const WCHAR name_prefix
[] = {'\\','D','E','V','I','C','E','\\','T','C','P','I','P','_',0};
1503 memcpy( row
->wszName
, name_prefix
, sizeof(name_prefix
) );
1504 ConvertGuidToStringW( &stat
->if_guid
, row
->wszName
+ ARRAY_SIZE(name_prefix
) - 1, CHARS_IN_GUID
);
1505 row
->dwIndex
= stat
->if_index
;
1506 row
->dwType
= stat
->type
;
1507 row
->dwMtu
= dyn
->mtu
;
1508 row
->dwSpeed
= dyn
->rcv_speed
;
1509 row
->dwPhysAddrLen
= rw
->phys_addr
.Length
;
1510 if (row
->dwPhysAddrLen
> sizeof(row
->bPhysAddr
)) row
->dwPhysAddrLen
= 0;
1511 memcpy( row
->bPhysAddr
, rw
->phys_addr
.Address
, row
->dwPhysAddrLen
);
1512 row
->dwAdminStatus
= rw
->admin_status
;
1513 row
->dwOperStatus
= (dyn
->oper_status
== IfOperStatusUp
) ? MIB_IF_OPER_STATUS_OPERATIONAL
: MIB_IF_OPER_STATUS_NON_OPERATIONAL
;
1514 row
->dwLastChange
= 0;
1515 row
->dwInOctets
= dyn
->in_octets
;
1516 row
->dwInUcastPkts
= dyn
->in_ucast_pkts
;
1517 row
->dwInNUcastPkts
= dyn
->in_bcast_pkts
+ dyn
->in_mcast_pkts
;
1518 row
->dwInDiscards
= dyn
->in_discards
;
1519 row
->dwInErrors
= dyn
->in_errors
;
1520 row
->dwInUnknownProtos
= 0;
1521 row
->dwOutOctets
= dyn
->out_octets
;
1522 row
->dwOutUcastPkts
= dyn
->out_ucast_pkts
;
1523 row
->dwOutNUcastPkts
= dyn
->out_bcast_pkts
+ dyn
->out_mcast_pkts
;
1524 row
->dwOutDiscards
= dyn
->out_discards
;
1525 row
->dwOutErrors
= dyn
->out_errors
;
1527 row
->dwDescrLen
= WideCharToMultiByte( CP_ACP
, 0, stat
->descr
.String
, stat
->descr
.Length
/ sizeof(WCHAR
),
1528 (char *)row
->bDescr
, sizeof(row
->bDescr
) - 1, NULL
, NULL
);
1529 row
->bDescr
[row
->dwDescrLen
] = '\0';
1532 /******************************************************************
1533 * GetIfEntry (IPHLPAPI.@)
1535 * Get information about an interface.
1538 * pIfRow [In/Out] In: dwIndex of MIB_IFROW selects the interface.
1539 * Out: interface information
1543 * Failure: error code from winerror.h
1545 DWORD WINAPI
GetIfEntry( MIB_IFROW
*row
)
1547 struct nsi_ndis_ifinfo_rw rw
;
1548 struct nsi_ndis_ifinfo_dynamic dyn
;
1549 struct nsi_ndis_ifinfo_static stat
;
1553 TRACE( "row %p\n", row
);
1554 if (!row
) return ERROR_INVALID_PARAMETER
;
1556 err
= ConvertInterfaceIndexToLuid( row
->dwIndex
, &luid
);
1557 if (err
) return err
;
1559 err
= NsiGetAllParameters( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
,
1560 &luid
, sizeof(luid
), &rw
, sizeof(rw
),
1561 &dyn
, sizeof(dyn
), &stat
, sizeof(stat
) );
1562 if (!err
) if_row_fill( row
, &rw
, &dyn
, &stat
);
1566 static int ifrow_cmp( const void *a
, const void *b
)
1568 return ((const MIB_IFROW
*)a
)->dwIndex
- ((const MIB_IFROW
*)b
)->dwIndex
;
1571 /******************************************************************
1572 * GetIfTable (IPHLPAPI.@)
1574 * Get a table of local interfaces.
1577 * table [Out] buffer for local interfaces table
1578 * size [In/Out] length of output buffer
1579 * sort [In] whether to sort the table
1583 * Failure: error code from winerror.h
1586 * If size is less than required, the function will return
1587 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to the required byte
1589 * If sort is true, the returned table will be sorted by interface index.
1591 DWORD WINAPI
GetIfTable( MIB_IFTABLE
*table
, ULONG
*size
, BOOL sort
)
1593 DWORD i
, count
, needed
, err
;
1595 struct nsi_ndis_ifinfo_rw
*rw
;
1596 struct nsi_ndis_ifinfo_dynamic
*dyn
;
1597 struct nsi_ndis_ifinfo_static
*stat
;
1599 if (!size
) return ERROR_INVALID_PARAMETER
;
1601 /* While this could be implemented on top of GetIfTable2(), it would require
1602 an additional copy of the data */
1603 err
= NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, (void **)&keys
, sizeof(*keys
),
1604 (void **)&rw
, sizeof(*rw
), (void **)&dyn
, sizeof(*dyn
),
1605 (void **)&stat
, sizeof(*stat
), &count
, 0 );
1606 if (err
) return err
;
1608 needed
= FIELD_OFFSET( MIB_IFTABLE
, table
[count
] );
1610 if (!table
|| *size
< needed
)
1613 err
= ERROR_INSUFFICIENT_BUFFER
;
1617 table
->dwNumEntries
= count
;
1618 for (i
= 0; i
< count
; i
++)
1620 MIB_IFROW
*row
= table
->table
+ i
;
1622 if_row_fill( row
, rw
+ i
, dyn
+ i
, stat
+ i
);
1625 if (sort
) qsort( table
->table
, count
, sizeof(MIB_IFROW
), ifrow_cmp
);
1628 NsiFreeTable( keys
, rw
, dyn
, stat
);
1632 /******************************************************************
1633 * AllocateAndGetIfTableFromStack (IPHLPAPI.@)
1635 * Get table of local interfaces.
1636 * Like GetIfTable(), but allocate the returned table from heap.
1639 * table [Out] pointer into which the MIB_IFTABLE is
1640 * allocated and returned.
1641 * sort [In] whether to sort the table
1642 * heap [In] heap from which the table is allocated
1643 * flags [In] flags to HeapAlloc
1646 * ERROR_INVALID_PARAMETER if ppIfTable is NULL, whatever
1647 * GetIfTable() returns otherwise.
1649 DWORD WINAPI
AllocateAndGetIfTableFromStack( MIB_IFTABLE
**table
, BOOL sort
, HANDLE heap
, DWORD flags
)
1651 DWORD i
, count
, size
, err
;
1653 struct nsi_ndis_ifinfo_rw
*rw
;
1654 struct nsi_ndis_ifinfo_dynamic
*dyn
;
1655 struct nsi_ndis_ifinfo_static
*stat
;
1657 if (!table
) return ERROR_INVALID_PARAMETER
;
1659 /* While this could be implemented on top of GetIfTable(), it would require
1660 an additional call to retrieve the size */
1661 err
= NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, (void **)&keys
, sizeof(*keys
),
1662 (void **)&rw
, sizeof(*rw
), (void **)&dyn
, sizeof(*dyn
),
1663 (void **)&stat
, sizeof(*stat
), &count
, 0 );
1664 if (err
) return err
;
1666 size
= FIELD_OFFSET( MIB_IFTABLE
, table
[count
] );
1667 *table
= HeapAlloc( heap
, flags
, size
);
1670 err
= ERROR_NOT_ENOUGH_MEMORY
;
1674 (*table
)->dwNumEntries
= count
;
1675 for (i
= 0; i
< count
; i
++)
1677 MIB_IFROW
*row
= (*table
)->table
+ i
;
1679 if_row_fill( row
, rw
+ i
, dyn
+ i
, stat
+ i
);
1681 if (sort
) qsort( (*table
)->table
, count
, sizeof(MIB_IFROW
), ifrow_cmp
);
1684 NsiFreeTable( keys
, rw
, dyn
, stat
);
1688 static void if_row2_fill( MIB_IF_ROW2
*row
, struct nsi_ndis_ifinfo_rw
*rw
, struct nsi_ndis_ifinfo_dynamic
*dyn
,
1689 struct nsi_ndis_ifinfo_static
*stat
)
1691 row
->InterfaceIndex
= stat
->if_index
;
1692 row
->InterfaceGuid
= stat
->if_guid
;
1693 if_counted_string_copy( row
->Alias
, ARRAY_SIZE(row
->Alias
), &rw
->alias
);
1694 if_counted_string_copy( row
->Description
, ARRAY_SIZE(row
->Description
), &stat
->descr
);
1695 row
->PhysicalAddressLength
= rw
->phys_addr
.Length
;
1696 if (row
->PhysicalAddressLength
> sizeof(row
->PhysicalAddress
)) row
->PhysicalAddressLength
= 0;
1697 memcpy( row
->PhysicalAddress
, rw
->phys_addr
.Address
, row
->PhysicalAddressLength
);
1698 memcpy( row
->PermanentPhysicalAddress
, stat
->perm_phys_addr
.Address
, row
->PhysicalAddressLength
);
1699 row
->Mtu
= dyn
->mtu
;
1700 row
->Type
= stat
->type
;
1701 row
->TunnelType
= TUNNEL_TYPE_NONE
; /* fixme */
1702 row
->MediaType
= stat
->media_type
;
1703 row
->PhysicalMediumType
= stat
->phys_medium_type
;
1704 row
->AccessType
= stat
->access_type
;
1705 row
->DirectionType
= NET_IF_DIRECTION_SENDRECEIVE
; /* fixme */
1706 row
->InterfaceAndOperStatusFlags
.HardwareInterface
= stat
->flags
.hw
;
1707 row
->InterfaceAndOperStatusFlags
.FilterInterface
= stat
->flags
.filter
;
1708 row
->InterfaceAndOperStatusFlags
.ConnectorPresent
= !!stat
->conn_present
;
1709 row
->InterfaceAndOperStatusFlags
.NotAuthenticated
= 0; /* fixme */
1710 row
->InterfaceAndOperStatusFlags
.NotMediaConnected
= dyn
->flags
.not_media_conn
;
1711 row
->InterfaceAndOperStatusFlags
.Paused
= 0; /* fixme */
1712 row
->InterfaceAndOperStatusFlags
.LowPower
= 0; /* fixme */
1713 row
->InterfaceAndOperStatusFlags
.EndPointInterface
= 0; /* fixme */
1714 row
->OperStatus
= dyn
->oper_status
;
1715 row
->AdminStatus
= rw
->admin_status
;
1716 row
->MediaConnectState
= dyn
->media_conn_state
;
1717 row
->NetworkGuid
= rw
->network_guid
;
1718 row
->ConnectionType
= stat
->conn_type
;
1719 row
->TransmitLinkSpeed
= dyn
->xmit_speed
;
1720 row
->ReceiveLinkSpeed
= dyn
->rcv_speed
;
1721 row
->InOctets
= dyn
->in_octets
;
1722 row
->InUcastPkts
= dyn
->in_ucast_pkts
;
1723 row
->InNUcastPkts
= dyn
->in_bcast_pkts
+ dyn
->in_mcast_pkts
;
1724 row
->InDiscards
= dyn
->in_discards
;
1725 row
->InErrors
= dyn
->in_errors
;
1726 row
->InUnknownProtos
= 0; /* fixme */
1727 row
->InUcastOctets
= dyn
->in_ucast_octs
;
1728 row
->InMulticastOctets
= dyn
->in_mcast_octs
;
1729 row
->InBroadcastOctets
= dyn
->in_bcast_octs
;
1730 row
->OutOctets
= dyn
->out_octets
;
1731 row
->OutUcastPkts
= dyn
->out_ucast_pkts
;
1732 row
->OutNUcastPkts
= dyn
->out_bcast_pkts
+ dyn
->out_mcast_pkts
;
1733 row
->OutDiscards
= dyn
->out_discards
;
1734 row
->OutErrors
= dyn
->out_errors
;
1735 row
->OutUcastOctets
= dyn
->out_ucast_octs
;
1736 row
->OutMulticastOctets
= dyn
->out_mcast_octs
;
1737 row
->OutBroadcastOctets
= dyn
->out_bcast_octs
;
1738 row
->OutQLen
= 0; /* fixme */
1741 /******************************************************************
1742 * GetIfEntry2Ex (IPHLPAPI.@)
1744 DWORD WINAPI
GetIfEntry2Ex( MIB_IF_TABLE_LEVEL level
, MIB_IF_ROW2
*row
)
1747 struct nsi_ndis_ifinfo_rw rw
;
1748 struct nsi_ndis_ifinfo_dynamic dyn
;
1749 struct nsi_ndis_ifinfo_static stat
;
1751 TRACE( "(%d, %p)\n", level
, row
);
1753 if (level
!= MibIfTableNormal
) FIXME( "level %u not fully supported\n", level
);
1754 if (!row
) return ERROR_INVALID_PARAMETER
;
1756 if (!row
->InterfaceLuid
.Value
)
1758 if (!row
->InterfaceIndex
) return ERROR_INVALID_PARAMETER
;
1759 err
= ConvertInterfaceIndexToLuid( row
->InterfaceIndex
, &row
->InterfaceLuid
);
1760 if (err
) return err
;
1763 err
= NsiGetAllParameters( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
,
1764 &row
->InterfaceLuid
, sizeof(row
->InterfaceLuid
),
1765 &rw
, sizeof(rw
), &dyn
, sizeof(dyn
), &stat
, sizeof(stat
) );
1766 if (!err
) if_row2_fill( row
, &rw
, &dyn
, &stat
);
1770 /******************************************************************
1771 * GetIfEntry2 (IPHLPAPI.@)
1773 DWORD WINAPI
GetIfEntry2( MIB_IF_ROW2
*row
)
1775 return GetIfEntry2Ex( MibIfTableNormal
, row
);
1778 /******************************************************************
1779 * GetIfTable2Ex (IPHLPAPI.@)
1781 DWORD WINAPI
GetIfTable2Ex( MIB_IF_TABLE_LEVEL level
, MIB_IF_TABLE2
**table
)
1783 DWORD i
, count
, size
, err
;
1785 struct nsi_ndis_ifinfo_rw
*rw
;
1786 struct nsi_ndis_ifinfo_dynamic
*dyn
;
1787 struct nsi_ndis_ifinfo_static
*stat
;
1789 TRACE( "level %u, table %p\n", level
, table
);
1791 if (!table
|| level
> MibIfTableNormalWithoutStatistics
)
1792 return ERROR_INVALID_PARAMETER
;
1794 if (level
!= MibIfTableNormal
)
1795 FIXME("level %u not fully supported\n", level
);
1797 err
= NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, (void **)&keys
, sizeof(*keys
),
1798 (void **)&rw
, sizeof(*rw
), (void **)&dyn
, sizeof(*dyn
),
1799 (void **)&stat
, sizeof(*stat
), &count
, 0 );
1800 if (err
) return err
;
1802 size
= FIELD_OFFSET( MIB_IF_TABLE2
, Table
[count
] );
1804 if (!(*table
= heap_alloc_zero( size
)))
1806 err
= ERROR_OUTOFMEMORY
;
1810 (*table
)->NumEntries
= count
;
1811 for (i
= 0; i
< count
; i
++)
1813 MIB_IF_ROW2
*row
= (*table
)->Table
+ i
;
1815 row
->InterfaceLuid
.Value
= keys
[i
].Value
;
1816 if_row2_fill( row
, rw
+ i
, dyn
+ i
, stat
+ i
);
1819 NsiFreeTable( keys
, rw
, dyn
, stat
);
1823 /******************************************************************
1824 * GetIfTable2 (IPHLPAPI.@)
1826 DWORD WINAPI
GetIfTable2( MIB_IF_TABLE2
**table
)
1828 TRACE( "table %p\n", table
);
1829 return GetIfTable2Ex( MibIfTableNormal
, table
);
1832 /******************************************************************
1833 * GetInterfaceInfo (IPHLPAPI.@)
1835 * Get a list of network interface adapters.
1838 * pIfTable [Out] buffer for interface adapters
1839 * dwOutBufLen [Out] if buffer is too small, returns required size
1843 * Failure: error code from winerror.h
1846 * MSDN states this should return non-loopback interfaces only.
1848 DWORD WINAPI
GetInterfaceInfo( IP_INTERFACE_INFO
*table
, ULONG
*size
)
1850 MIB_IFTABLE
*if_table
;
1851 DWORD err
, needed
, i
;
1853 TRACE("table %p, size %p\n", table
, size
);
1854 if (!size
) return ERROR_INVALID_PARAMETER
;
1856 err
= AllocateAndGetIfTableFromStack( &if_table
, 0, GetProcessHeap(), 0 );
1857 if (err
) return err
;
1859 needed
= FIELD_OFFSET(IP_INTERFACE_INFO
, Adapter
[if_table
->dwNumEntries
]);
1860 if (!table
|| *size
< needed
)
1863 heap_free( if_table
);
1864 return ERROR_INSUFFICIENT_BUFFER
;
1867 table
->NumAdapters
= if_table
->dwNumEntries
;
1868 for (i
= 0; i
< if_table
->dwNumEntries
; i
++)
1870 table
->Adapter
[i
].Index
= if_table
->table
[i
].dwIndex
;
1871 strcpyW( table
->Adapter
[i
].Name
, if_table
->table
[i
].wszName
);
1873 heap_free( if_table
);
1874 return ERROR_SUCCESS
;
1877 static int ipaddrrow_cmp( const void *a
, const void *b
)
1879 return ((const MIB_IPADDRROW
*)a
)->dwAddr
- ((const MIB_IPADDRROW
*)b
)->dwAddr
;
1882 /******************************************************************
1883 * GetIpAddrTable (IPHLPAPI.@)
1885 * Get interface-to-IP address mapping table.
1888 * table [Out] buffer for mapping table
1889 * size [In/Out] length of output buffer
1890 * sort [In] whether to sort the table
1894 * Failure: error code from winerror.h
1897 DWORD WINAPI
GetIpAddrTable( MIB_IPADDRTABLE
*table
, ULONG
*size
, BOOL sort
)
1899 DWORD err
, count
, needed
, i
, loopback
, row_num
= 0;
1900 struct nsi_ipv4_unicast_key
*keys
;
1901 struct nsi_ip_unicast_rw
*rw
;
1903 TRACE( "table %p, size %p, sort %d\n", table
, size
, sort
);
1904 if (!size
) return ERROR_INVALID_PARAMETER
;
1906 err
= NsiAllocateAndGetTable( 1, &NPI_MS_IPV4_MODULEID
, NSI_IP_UNICAST_TABLE
, (void **)&keys
, sizeof(*keys
),
1907 (void **)&rw
, sizeof(*rw
), NULL
, 0, NULL
, 0, &count
, 0 );
1908 if (err
) return err
;
1910 needed
= FIELD_OFFSET( MIB_IPADDRTABLE
, table
[count
] );
1912 if (!table
|| *size
< needed
)
1915 err
= ERROR_INSUFFICIENT_BUFFER
;
1919 table
->dwNumEntries
= count
;
1921 for (loopback
= 0; loopback
< 2; loopback
++) /* Move the loopback addresses to the end */
1923 for (i
= 0; i
< count
; i
++)
1925 MIB_IPADDRROW
*row
= table
->table
+ row_num
;
1927 if (!!loopback
!= (keys
[i
].luid
.Info
.IfType
== MIB_IF_TYPE_LOOPBACK
)) continue;
1929 row
->dwAddr
= keys
[i
].addr
.WS_s_addr
;
1930 ConvertInterfaceLuidToIndex( &keys
[i
].luid
, &row
->dwIndex
);
1931 ConvertLengthToIpv4Mask( rw
[i
].on_link_prefix
, &row
->dwMask
);
1932 row
->dwBCastAddr
= 1;
1933 row
->dwReasmSize
= 0xffff;
1935 row
->wType
= MIB_IPADDR_PRIMARY
;
1940 if (sort
) qsort( table
->table
, count
, sizeof(MIB_IPADDRROW
), ipaddrrow_cmp
);
1942 NsiFreeTable( keys
, rw
, NULL
, NULL
);
1948 /******************************************************************
1949 * AllocateAndGetIpAddrTableFromStack (IPHLPAPI.@)
1951 * Get interface-to-IP address mapping table.
1952 * Like GetIpAddrTable(), but allocate the returned table from heap.
1955 * table [Out] pointer into which the MIB_IPADDRTABLE is
1956 * allocated and returned.
1957 * sort [In] whether to sort the table
1958 * heap [In] heap from which the table is allocated
1959 * flags [In] flags to HeapAlloc
1962 DWORD WINAPI
AllocateAndGetIpAddrTableFromStack( MIB_IPADDRTABLE
**table
, BOOL sort
, HANDLE heap
, DWORD flags
)
1964 DWORD err
, size
= FIELD_OFFSET(MIB_IPADDRTABLE
, table
[2]), attempt
;
1966 TRACE( "table %p, sort %d, heap %p, flags 0x%08x\n", table
, sort
, heap
, flags
);
1968 for (attempt
= 0; attempt
< 5; attempt
++)
1970 *table
= HeapAlloc( heap
, flags
, size
);
1971 if (!*table
) return ERROR_NOT_ENOUGH_MEMORY
;
1973 err
= GetIpAddrTable( *table
, &size
, sort
);
1975 HeapFree( heap
, flags
, *table
);
1976 if (err
!= ERROR_INSUFFICIENT_BUFFER
) break;
1982 static int ipforward_row_cmp( const void *a
, const void *b
)
1984 const MIB_IPFORWARDROW
*rowA
= a
;
1985 const MIB_IPFORWARDROW
*rowB
= b
;
1988 if ((ret
= rowA
->dwForwardDest
- rowB
->dwForwardDest
) != 0) return ret
;
1989 if ((ret
= rowA
->u2
.dwForwardProto
- rowB
->u2
.dwForwardProto
) != 0) return ret
;
1990 if ((ret
= rowA
->dwForwardPolicy
- rowB
->dwForwardPolicy
) != 0) return ret
;
1991 return rowA
->dwForwardNextHop
- rowB
->dwForwardNextHop
;
1994 /******************************************************************
1995 * GetIpForwardTable (IPHLPAPI.@)
1997 * Get the route table.
2000 * table [Out] buffer for route table
2001 * size [In/Out] length of output buffer
2002 * sort [In] whether to sort the table
2006 * Failure: error code from winerror.h
2008 DWORD WINAPI
GetIpForwardTable( MIB_IPFORWARDTABLE
*table
, ULONG
*size
, BOOL sort
)
2010 DWORD err
, count
, uni_count
, needed
, i
, addr
;
2011 struct nsi_ipv4_forward_key
*keys
;
2012 struct nsi_ip_forward_rw
*rw
;
2013 struct nsi_ipv4_forward_dynamic
*dyn
;
2014 struct nsi_ip_forward_static
*stat
;
2015 struct nsi_ipv4_unicast_key
*uni_keys
= NULL
;
2017 TRACE( "table %p, size %p, sort %d\n", table
, size
, sort
);
2018 if (!size
) return ERROR_INVALID_PARAMETER
;
2020 err
= NsiAllocateAndGetTable( 1, &NPI_MS_IPV4_MODULEID
, NSI_IP_FORWARD_TABLE
, (void **)&keys
, sizeof(*keys
),
2021 (void **)&rw
, sizeof(*rw
), (void **)&dyn
, sizeof(*dyn
),
2022 (void **)&stat
, sizeof(*stat
), &count
, 0 );
2023 if (err
) return err
;
2025 needed
= FIELD_OFFSET( MIB_IPFORWARDTABLE
, table
[count
] );
2027 if (!table
|| *size
< needed
)
2030 err
= ERROR_INSUFFICIENT_BUFFER
;
2034 err
= NsiAllocateAndGetTable( 1, &NPI_MS_IPV4_MODULEID
, NSI_IP_UNICAST_TABLE
, (void **)&uni_keys
, sizeof(*uni_keys
),
2035 NULL
, 0, NULL
, 0, NULL
, 0, &uni_count
, 0 );
2038 table
->dwNumEntries
= count
;
2039 for (i
= 0; i
< count
; i
++)
2041 MIB_IPFORWARDROW
*row
= table
->table
+ i
;
2043 row
->dwForwardDest
= keys
[i
].prefix
.WS_s_addr
;
2044 ConvertLengthToIpv4Mask( keys
[i
].prefix_len
, &row
->dwForwardMask
);
2045 row
->dwForwardPolicy
= 0;
2046 row
->dwForwardNextHop
= keys
[i
].next_hop
.WS_s_addr
;
2047 row
->u1
.dwForwardType
= row
->dwForwardNextHop
? MIB_IPROUTE_TYPE_INDIRECT
: MIB_IPROUTE_TYPE_DIRECT
;
2048 if (!row
->dwForwardNextHop
) /* find the interface's addr */
2050 for (addr
= 0; addr
< uni_count
; addr
++)
2052 if (uni_keys
[addr
].luid
.Value
== keys
[i
].luid
.Value
)
2054 row
->dwForwardNextHop
= uni_keys
[addr
].addr
.WS_s_addr
;
2059 row
->dwForwardIfIndex
= stat
[i
].if_index
;
2060 row
->u2
.dwForwardProto
= rw
[i
].protocol
;
2061 row
->dwForwardAge
= dyn
[i
].age
;
2062 row
->dwForwardNextHopAS
= 0;
2063 row
->dwForwardMetric1
= rw
[i
].metric
; /* FIXME: add interface metric */
2064 row
->dwForwardMetric2
= 0;
2065 row
->dwForwardMetric3
= 0;
2066 row
->dwForwardMetric4
= 0;
2067 row
->dwForwardMetric5
= 0;
2070 if (sort
) qsort( table
->table
, count
, sizeof(MIB_IPFORWARDROW
), ipforward_row_cmp
);
2072 NsiFreeTable( uni_keys
, NULL
, NULL
, NULL
);
2073 NsiFreeTable( keys
, rw
, dyn
, stat
);
2078 /******************************************************************
2079 * AllocateAndGetIpForwardTableFromStack (IPHLPAPI.@)
2081 * Get the route table.
2082 * Like GetIpForwardTable(), but allocate the returned table from heap.
2085 * table [Out] pointer into which the MIB_IPFORWARDTABLE is
2086 * allocated and returned.
2087 * sort [In] whether to sort the table
2088 * heap [In] heap from which the table is allocated
2089 * flags [In] flags to HeapAlloc
2092 * ERROR_INVALID_PARAMETER if ppIfTable is NULL, other error codes
2093 * on failure, NO_ERROR on success.
2095 DWORD WINAPI
AllocateAndGetIpForwardTableFromStack( MIB_IPFORWARDTABLE
**table
, BOOL sort
, HANDLE heap
, DWORD flags
)
2097 DWORD err
, size
= FIELD_OFFSET(MIB_IPFORWARDTABLE
, table
[2]), attempt
;
2099 TRACE( "table %p, sort %d, heap %p, flags 0x%08x\n", table
, sort
, heap
, flags
);
2101 for (attempt
= 0; attempt
< 5; attempt
++)
2103 *table
= HeapAlloc( heap
, flags
, size
);
2104 if (!*table
) return ERROR_NOT_ENOUGH_MEMORY
;
2106 err
= GetIpForwardTable( *table
, &size
, sort
);
2108 HeapFree( heap
, flags
, *table
);
2109 if (err
!= ERROR_INSUFFICIENT_BUFFER
) break;
2115 static void forward_row2_fill( MIB_IPFORWARD_ROW2
*row
, USHORT fam
, void *key
, struct nsi_ip_forward_rw
*rw
,
2116 void *dyn
, struct nsi_ip_forward_static
*stat
)
2118 struct nsi_ipv4_forward_key
*key4
= (struct nsi_ipv4_forward_key
*)key
;
2119 struct nsi_ipv6_forward_key
*key6
= (struct nsi_ipv6_forward_key
*)key
;
2120 struct nsi_ipv4_forward_dynamic
*dyn4
= (struct nsi_ipv4_forward_dynamic
*)dyn
;
2121 struct nsi_ipv6_forward_dynamic
*dyn6
= (struct nsi_ipv6_forward_dynamic
*)dyn
;
2123 if (fam
== WS_AF_INET
)
2125 row
->InterfaceLuid
= key4
->luid
;
2126 row
->DestinationPrefix
.Prefix
.Ipv4
.sin_family
= fam
;
2127 row
->DestinationPrefix
.Prefix
.Ipv4
.sin_port
= 0;
2128 row
->DestinationPrefix
.Prefix
.Ipv4
.sin_addr
= key4
->prefix
;
2129 memset( &row
->DestinationPrefix
.Prefix
.Ipv4
.sin_zero
, 0, sizeof(row
->DestinationPrefix
.Prefix
.Ipv4
.sin_zero
) );
2130 row
->DestinationPrefix
.PrefixLength
= key4
->prefix_len
;
2131 row
->NextHop
.Ipv4
.sin_family
= fam
;
2132 row
->NextHop
.Ipv4
.sin_port
= 0;
2133 row
->NextHop
.Ipv4
.sin_addr
= key4
->next_hop
;
2134 memset( &row
->NextHop
.Ipv4
.sin_zero
, 0, sizeof(row
->NextHop
.Ipv4
.sin_zero
) );
2136 row
->Age
= dyn4
->age
;
2140 row
->InterfaceLuid
= key6
->luid
;
2142 row
->DestinationPrefix
.Prefix
.Ipv6
.sin6_family
= fam
;
2143 row
->DestinationPrefix
.Prefix
.Ipv6
.sin6_port
= 0;
2144 row
->DestinationPrefix
.Prefix
.Ipv6
.sin6_flowinfo
= 0;
2145 row
->DestinationPrefix
.Prefix
.Ipv6
.sin6_addr
= key6
->prefix
;
2146 row
->DestinationPrefix
.Prefix
.Ipv6
.sin6_scope_id
= 0;
2147 row
->DestinationPrefix
.PrefixLength
= key6
->prefix_len
;
2148 row
->NextHop
.Ipv6
.sin6_family
= fam
;
2149 row
->NextHop
.Ipv6
.sin6_port
= 0;
2150 row
->NextHop
.Ipv6
.sin6_flowinfo
= 0;
2151 row
->NextHop
.Ipv6
.sin6_addr
= key6
->next_hop
;
2152 row
->NextHop
.Ipv6
.sin6_scope_id
= 0;
2154 row
->Age
= dyn6
->age
;
2157 row
->InterfaceIndex
= stat
->if_index
;
2159 row
->SitePrefixLength
= rw
->site_prefix_len
;
2160 row
->ValidLifetime
= rw
->valid_lifetime
;
2161 row
->PreferredLifetime
= rw
->preferred_lifetime
;
2162 row
->Metric
= rw
->metric
;
2163 row
->Protocol
= rw
->protocol
;
2164 row
->Loopback
= rw
->loopback
;
2165 row
->AutoconfigureAddress
= rw
->autoconf
;
2166 row
->Publish
= rw
->publish
;
2167 row
->Immortal
= rw
->immortal
;
2169 row
->Origin
= stat
->origin
;
2172 /******************************************************************
2173 * GetIpForwardTable2 (IPHLPAPI.@)
2175 DWORD WINAPI
GetIpForwardTable2( ADDRESS_FAMILY family
, MIB_IPFORWARD_TABLE2
**table
)
2177 void *key
[2] = { NULL
, NULL
};
2178 struct nsi_ip_forward_rw
*rw
[2] = { NULL
, NULL
};
2179 void *dyn
[2] = { NULL
, NULL
};
2180 struct nsi_ip_forward_static
*stat
[2] = { NULL
, NULL
};
2181 static const USHORT fam
[2] = { WS_AF_INET
, WS_AF_INET6
};
2182 static const DWORD key_size
[2] = { sizeof(struct nsi_ipv4_forward_key
), sizeof(struct nsi_ipv6_forward_key
) };
2183 static const DWORD dyn_size
[2] = { sizeof(struct nsi_ipv4_forward_dynamic
), sizeof(struct nsi_ipv6_forward_dynamic
) };
2184 DWORD err
= ERROR_SUCCESS
, i
, size
, count
[2] = { 0, 0 };
2186 TRACE( "%u, %p\n", family
, table
);
2188 if (!table
|| (family
!= WS_AF_INET
&& family
!= WS_AF_INET6
&& family
!= WS_AF_UNSPEC
))
2189 return ERROR_INVALID_PARAMETER
;
2191 for (i
= 0; i
< 2; i
++)
2193 if (family
!= WS_AF_UNSPEC
&& family
!= fam
[i
]) continue;
2195 err
= NsiAllocateAndGetTable( 1, ip_module_id( fam
[i
] ), NSI_IP_FORWARD_TABLE
, key
+ i
, key_size
[i
],
2196 (void **)rw
+ i
, sizeof(**rw
), dyn
+ i
, dyn_size
[i
],
2197 (void **)stat
+ i
, sizeof(**stat
), count
+ i
, 0 );
2198 if (err
) count
[i
] = 0;
2201 size
= FIELD_OFFSET(MIB_IPFORWARD_TABLE2
, Table
[ count
[0] + count
[1] ]);
2202 *table
= heap_alloc( size
);
2205 err
= ERROR_NOT_ENOUGH_MEMORY
;
2209 (*table
)->NumEntries
= count
[0] + count
[1];
2210 for (i
= 0; i
< count
[0]; i
++)
2212 MIB_IPFORWARD_ROW2
*row
= (*table
)->Table
+ i
;
2213 struct nsi_ipv4_forward_key
*key4
= (struct nsi_ipv4_forward_key
*)key
[0];
2214 struct nsi_ipv4_forward_dynamic
*dyn4
= (struct nsi_ipv4_forward_dynamic
*)dyn
[0];
2216 forward_row2_fill( row
, fam
[0], key4
+ i
, rw
[0] + i
, dyn4
+ i
, stat
[0] + i
);
2219 for (i
= 0; i
< count
[1]; i
++)
2221 MIB_IPFORWARD_ROW2
*row
= (*table
)->Table
+ count
[0] + i
;
2222 struct nsi_ipv6_forward_key
*key6
= (struct nsi_ipv6_forward_key
*)key
[1];
2223 struct nsi_ipv6_forward_dynamic
*dyn6
= (struct nsi_ipv6_forward_dynamic
*)dyn
[1];
2225 forward_row2_fill( row
, fam
[1], key6
+ i
, rw
[1] + i
, dyn6
+ i
, stat
[1] + i
);
2229 for (i
= 0; i
< 2; i
++) NsiFreeTable( key
[i
], rw
[i
], dyn
[i
], stat
[i
] );
2233 static int ipnetrow_cmp( const void *a
, const void *b
)
2235 const MIB_IPNETROW
*row_a
= a
;
2236 const MIB_IPNETROW
*row_b
= b
;
2238 return RtlUlongByteSwap( row_a
->dwAddr
) - RtlUlongByteSwap( row_b
->dwAddr
);
2241 /******************************************************************
2242 * GetIpNetTable (IPHLPAPI.@)
2244 * Get the IP-to-physical address mapping table.
2247 * table [Out] buffer for mapping table
2248 * size [In/Out] length of output buffer
2249 * sort [In] whether to sort the table
2253 * Failure: error code from winerror.h
2256 DWORD WINAPI
GetIpNetTable( MIB_IPNETTABLE
*table
, ULONG
*size
, BOOL sort
)
2258 DWORD err
, count
, needed
, i
;
2259 struct nsi_ipv4_neighbour_key
*keys
;
2260 struct nsi_ip_neighbour_rw
*rw
;
2261 struct nsi_ip_neighbour_dynamic
*dyn
;
2263 TRACE( "table %p, size %p, sort %d\n", table
, size
, sort
);
2265 if (!size
) return ERROR_INVALID_PARAMETER
;
2267 err
= NsiAllocateAndGetTable( 1, &NPI_MS_IPV4_MODULEID
, NSI_IP_NEIGHBOUR_TABLE
, (void **)&keys
, sizeof(*keys
),
2268 (void **)&rw
, sizeof(*rw
), (void **)&dyn
, sizeof(*dyn
),
2269 NULL
, 0, &count
, 0 );
2270 if (err
) return err
;
2272 needed
= FIELD_OFFSET( MIB_IPNETTABLE
, table
[count
] );
2274 if (!table
|| *size
< needed
)
2277 err
= ERROR_INSUFFICIENT_BUFFER
;
2281 table
->dwNumEntries
= count
;
2282 for (i
= 0; i
< count
; i
++)
2284 MIB_IPNETROW
*row
= table
->table
+ i
;
2286 ConvertInterfaceLuidToIndex( &keys
[i
].luid
, &row
->dwIndex
);
2287 row
->dwPhysAddrLen
= dyn
[i
].phys_addr_len
;
2288 if (row
->dwPhysAddrLen
> sizeof(row
->bPhysAddr
)) row
->dwPhysAddrLen
= 0;
2289 memcpy( row
->bPhysAddr
, rw
[i
].phys_addr
, row
->dwPhysAddrLen
);
2290 memset( row
->bPhysAddr
+ row
->dwPhysAddrLen
, 0,
2291 sizeof(row
->bPhysAddr
) - row
->dwPhysAddrLen
);
2292 row
->dwAddr
= keys
[i
].addr
.WS_s_addr
;
2295 case NlnsUnreachable
:
2296 case NlnsIncomplete
:
2297 row
->u
.Type
= MIB_IPNET_TYPE_INVALID
;
2303 row
->u
.Type
= MIB_IPNET_TYPE_DYNAMIC
;
2306 row
->u
.Type
= MIB_IPNET_TYPE_STATIC
;
2309 row
->u
.Type
= MIB_IPNET_TYPE_OTHER
;
2313 if (sort
) qsort( table
->table
, table
->dwNumEntries
, sizeof(*table
->table
), ipnetrow_cmp
);
2316 NsiFreeTable( keys
, rw
, dyn
, NULL
);
2320 /******************************************************************
2321 * AllocateAndGetIpNetTableFromStack (IPHLPAPI.@)
2323 DWORD WINAPI
AllocateAndGetIpNetTableFromStack( MIB_IPNETTABLE
**table
, BOOL sort
, HANDLE heap
, DWORD flags
)
2325 DWORD err
, size
= FIELD_OFFSET(MIB_IPNETTABLE
, table
[2]), attempt
;
2327 TRACE( "table %p, sort %d, heap %p, flags 0x%08x\n", table
, sort
, heap
, flags
);
2329 for (attempt
= 0; attempt
< 5; attempt
++)
2331 *table
= HeapAlloc( heap
, flags
, size
);
2332 if (!*table
) return ERROR_NOT_ENOUGH_MEMORY
;
2334 err
= GetIpNetTable( *table
, &size
, sort
);
2336 HeapFree( heap
, flags
, *table
);
2337 if (err
!= ERROR_INSUFFICIENT_BUFFER
) break;
2343 static void ipnet_row2_fill( MIB_IPNET_ROW2
*row
, USHORT fam
, void *key
, struct nsi_ip_neighbour_rw
*rw
,
2344 struct nsi_ip_neighbour_dynamic
*dyn
)
2346 struct nsi_ipv4_neighbour_key
*key4
= (struct nsi_ipv4_neighbour_key
*)key
;
2347 struct nsi_ipv6_neighbour_key
*key6
= (struct nsi_ipv6_neighbour_key
*)key
;
2349 if (fam
== WS_AF_INET
)
2351 row
->Address
.Ipv4
.sin_family
= fam
;
2352 row
->Address
.Ipv4
.sin_port
= 0;
2353 row
->Address
.Ipv4
.sin_addr
= key4
->addr
;
2354 memset( &row
->Address
.Ipv4
.sin_zero
, 0, sizeof(row
->Address
.Ipv4
.sin_zero
) );
2355 row
->InterfaceLuid
= key4
->luid
;
2359 row
->Address
.Ipv6
.sin6_family
= fam
;
2360 row
->Address
.Ipv6
.sin6_port
= 0;
2361 row
->Address
.Ipv6
.sin6_flowinfo
= 0;
2362 row
->Address
.Ipv6
.sin6_addr
= key6
->addr
;
2363 row
->Address
.Ipv6
.sin6_scope_id
= 0;
2364 row
->InterfaceLuid
= key6
->luid
;
2367 ConvertInterfaceLuidToIndex( &row
->InterfaceLuid
, &row
->InterfaceIndex
);
2369 row
->PhysicalAddressLength
= dyn
->phys_addr_len
;
2370 if (row
->PhysicalAddressLength
> sizeof(row
->PhysicalAddress
))
2371 row
->PhysicalAddressLength
= 0;
2372 memcpy( row
->PhysicalAddress
, rw
->phys_addr
, row
->PhysicalAddressLength
);
2373 memset( row
->PhysicalAddress
+ row
->PhysicalAddressLength
, 0,
2374 sizeof(row
->PhysicalAddress
) - row
->PhysicalAddressLength
);
2375 row
->State
= dyn
->state
;
2377 row
->u
.s
.IsRouter
= dyn
->flags
.is_router
;
2378 row
->u
.s
.IsUnreachable
= dyn
->flags
.is_unreachable
;
2379 row
->ReachabilityTime
.LastReachable
= dyn
->time
;
2382 /******************************************************************
2383 * GetIpNetTable2 (IPHLPAPI.@)
2385 DWORD WINAPI
GetIpNetTable2( ADDRESS_FAMILY family
, MIB_IPNET_TABLE2
**table
)
2387 void *key
[2] = { NULL
, NULL
};
2388 struct nsi_ip_neighbour_rw
*rw
[2] = { NULL
, NULL
};
2389 struct nsi_ip_neighbour_dynamic
*dyn
[2] = { NULL
, NULL
};
2390 static const USHORT fam
[2] = { WS_AF_INET
, WS_AF_INET6
};
2391 static const DWORD key_size
[2] = { sizeof(struct nsi_ipv4_neighbour_key
), sizeof(struct nsi_ipv6_neighbour_key
) };
2392 DWORD err
= ERROR_SUCCESS
, i
, size
, count
[2] = { 0, 0 };
2394 TRACE( "%u, %p\n", family
, table
);
2396 if (!table
|| (family
!= WS_AF_INET
&& family
!= WS_AF_INET6
&& family
!= WS_AF_UNSPEC
))
2397 return ERROR_INVALID_PARAMETER
;
2399 for (i
= 0; i
< 2; i
++)
2401 if (family
!= WS_AF_UNSPEC
&& family
!= fam
[i
]) continue;
2403 err
= NsiAllocateAndGetTable( 1, ip_module_id( fam
[i
] ), NSI_IP_NEIGHBOUR_TABLE
, key
+ i
, key_size
[i
],
2404 (void **)rw
+ i
, sizeof(**rw
), (void **)dyn
+ i
, sizeof(**dyn
),
2405 NULL
, 0, count
+ i
, 0 );
2406 if (err
) count
[i
] = 0;
2409 size
= FIELD_OFFSET(MIB_IPNET_TABLE2
, Table
[ count
[0] + count
[1] ]);
2410 *table
= heap_alloc( size
);
2413 err
= ERROR_NOT_ENOUGH_MEMORY
;
2417 (*table
)->NumEntries
= count
[0] + count
[1];
2418 for (i
= 0; i
< count
[0]; i
++)
2420 MIB_IPNET_ROW2
*row
= (*table
)->Table
+ i
;
2421 struct nsi_ipv4_neighbour_key
*key4
= (struct nsi_ipv4_neighbour_key
*)key
[0];
2423 ipnet_row2_fill( row
, fam
[0], key4
+ i
, rw
[0] + i
, dyn
[0] + i
);
2426 for (i
= 0; i
< count
[1]; i
++)
2428 MIB_IPNET_ROW2
*row
= (*table
)->Table
+ count
[0] + i
;
2429 struct nsi_ipv6_neighbour_key
*key6
= (struct nsi_ipv6_neighbour_key
*)key
[1];
2431 ipnet_row2_fill( row
, fam
[1], key6
+ i
, rw
[1] + i
, dyn
[1] + i
);
2435 for (i
= 0; i
< 2; i
++) NsiFreeTable( key
[i
], rw
[i
], dyn
[i
], NULL
);
2439 /* Gets the DNS server list into the list beginning at list. Assumes that
2440 * a single server address may be placed at list if *len is at least
2441 * sizeof(IP_ADDR_STRING) long. Otherwise, list->Next is set to firstDynamic,
2442 * and assumes that all remaining DNS servers are contiguously located
2443 * beginning at second. On input, *len is assumed to be the total number
2444 * of bytes available for all DNS servers, and is ignored if list is NULL.
2445 * On return, *len is set to the total number of bytes required for all DNS
2447 * Returns ERROR_BUFFER_OVERFLOW if *len is insufficient,
2448 * ERROR_SUCCESS otherwise.
2450 static DWORD
get_dns_server_list( const NET_LUID
*luid
, IP_ADDR_STRING
*list
, IP_ADDR_STRING
*second
, DWORD
*len
)
2452 char buf
[FIELD_OFFSET(IP4_ARRAY
, AddrArray
[3])];
2453 IP4_ARRAY
*servers
= (IP4_ARRAY
*)buf
;
2454 DWORD needed
, num
, err
, i
, array_len
= sizeof(buf
);
2455 IP_ADDR_STRING
*ptr
;
2457 if (luid
&& luid
->Info
.IfType
== MIB_IF_TYPE_LOOPBACK
) return ERROR_NO_DATA
;
2461 err
= DnsQueryConfig( DnsConfigDnsServerList
, 0, NULL
, NULL
, servers
, &array_len
);
2462 num
= (array_len
- FIELD_OFFSET(IP4_ARRAY
, AddrArray
[0])) / sizeof(IP4_ADDRESS
);
2463 needed
= num
* sizeof(IP_ADDR_STRING
);
2464 if (!list
|| *len
< needed
)
2467 err
= ERROR_BUFFER_OVERFLOW
;
2472 if ((char *)servers
!= buf
) heap_free( servers
);
2473 servers
= heap_alloc( array_len
);
2476 err
= ERROR_NOT_ENOUGH_MEMORY
;
2483 for (i
= 0, ptr
= list
; i
< num
; i
++, ptr
= ptr
->Next
)
2485 RtlIpv4AddressToStringA( (IN_ADDR
*)&servers
->AddrArray
[i
], ptr
->IpAddress
.String
);
2486 if (i
== num
- 1) ptr
->Next
= NULL
;
2487 else if (i
== 0) ptr
->Next
= second
;
2488 else ptr
->Next
= ptr
+ 1;
2492 if ((char *)servers
!= buf
) heap_free( servers
);
2496 /******************************************************************
2497 * GetNetworkParams (IPHLPAPI.@)
2499 * Get the network parameters for the local computer.
2502 * info [Out] buffer for network parameters
2503 * size [In/Out] length of output buffer
2507 * Failure: error code from winerror.h
2510 * If size is less than required, the function will return
2511 * ERROR_INSUFFICIENT_BUFFER, and size will be set to the required byte
2514 DWORD WINAPI
GetNetworkParams( FIXED_INFO
*info
, ULONG
*size
)
2516 DWORD needed
= sizeof(*info
), dns_size
, err
;
2517 MIB_IPSTATS ip_stats
;
2520 TRACE( "info %p, size %p\n", info
, size
);
2521 if (!size
) return ERROR_INVALID_PARAMETER
;
2523 if (get_dns_server_list( NULL
, NULL
, NULL
, &dns_size
) == ERROR_BUFFER_OVERFLOW
)
2524 needed
+= dns_size
- sizeof(IP_ADDR_STRING
);
2525 if (!info
|| *size
< needed
)
2528 return ERROR_BUFFER_OVERFLOW
;
2532 memset( info
, 0, needed
);
2533 needed
= sizeof(info
->HostName
);
2534 GetComputerNameExA( ComputerNameDnsHostname
, info
->HostName
, &needed
);
2535 needed
= sizeof(info
->DomainName
);
2536 GetComputerNameExA( ComputerNameDnsDomain
, info
->DomainName
, &needed
);
2537 get_dns_server_list( NULL
, &info
->DnsServerList
, (IP_ADDR_STRING
*)(info
+ 1), &dns_size
);
2538 info
->CurrentDnsServer
= &info
->DnsServerList
;
2539 info
->NodeType
= HYBRID_NODETYPE
;
2540 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP",
2541 0, KEY_READ
, &key
);
2543 err
= RegOpenKeyExA( HKEY_LOCAL_MACHINE
, "SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters",
2544 0, KEY_READ
, &key
);
2547 needed
= sizeof(info
->ScopeId
);
2548 RegQueryValueExA( key
, "ScopeID", NULL
, NULL
, (BYTE
*)info
->ScopeId
, &needed
);
2552 if (!GetIpStatistics( &ip_stats
))
2553 info
->EnableRouting
= (ip_stats
.u
.Forwarding
== MIB_IP_FORWARDING
);
2555 return ERROR_SUCCESS
;
2559 /******************************************************************
2560 * GetNumberOfInterfaces (IPHLPAPI.@)
2562 * Get the number of interfaces.
2565 * pdwNumIf [Out] number of interfaces
2568 * NO_ERROR on success, ERROR_INVALID_PARAMETER if pdwNumIf is NULL.
2570 DWORD WINAPI
GetNumberOfInterfaces( DWORD
*count
)
2574 TRACE( "count %p\n", count
);
2575 if (!count
) return ERROR_INVALID_PARAMETER
;
2577 err
= NsiEnumerateObjectsAllParameters( 1, 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, NULL
, 0,
2578 NULL
, 0, NULL
, 0, NULL
, 0, &num
);
2579 *count
= err
? 0 : num
;
2583 /******************************************************************
2584 * GetPerAdapterInfo (IPHLPAPI.@)
2586 * Get information about an adapter corresponding to an interface.
2589 * IfIndex [In] interface info
2590 * pPerAdapterInfo [Out] buffer for per adapter info
2591 * pOutBufLen [In/Out] length of output buffer
2595 * Failure: error code from winerror.h
2597 DWORD WINAPI
GetPerAdapterInfo( ULONG index
, IP_PER_ADAPTER_INFO
*info
, ULONG
*size
)
2599 DWORD needed
= sizeof(*info
), dns_size
;
2602 TRACE( "(index %d, info %p, size %p)\n", index
, info
, size
);
2604 if (!size
) return ERROR_INVALID_PARAMETER
;
2605 if (ConvertInterfaceIndexToLuid( index
, &luid
)) return ERROR_NO_DATA
;
2607 if (get_dns_server_list( &luid
, NULL
, NULL
, &dns_size
) == ERROR_BUFFER_OVERFLOW
)
2608 needed
+= dns_size
- sizeof(IP_ADDR_STRING
);
2610 if (!info
|| *size
< needed
)
2613 return ERROR_BUFFER_OVERFLOW
;
2616 memset( info
, 0, needed
);
2617 get_dns_server_list( &luid
, &info
->DnsServerList
, (IP_ADDR_STRING
*)(info
+ 1), &dns_size
);
2618 info
->CurrentDnsServer
= &info
->DnsServerList
;
2620 /* FIXME Autoconfig: get unicast addresses and compare to 169.254.x.x */
2621 return ERROR_SUCCESS
;
2625 /******************************************************************
2626 * GetRTTAndHopCount (IPHLPAPI.@)
2628 * Get round-trip time (RTT) and hop count.
2632 * DestIpAddress [In] destination address to get the info for
2633 * HopCount [Out] retrieved hop count
2634 * MaxHops [In] maximum hops to search for the destination
2635 * RTT [Out] RTT in milliseconds
2642 * Stub, returns FALSE.
2644 BOOL WINAPI
GetRTTAndHopCount(IPAddr DestIpAddress
, PULONG HopCount
, ULONG MaxHops
, PULONG RTT
)
2646 FIXME("(DestIpAddress 0x%08x, HopCount %p, MaxHops %d, RTT %p): stub\n",
2647 DestIpAddress
, HopCount
, MaxHops
, RTT
);
2652 /******************************************************************
2653 * GetTcpTable (IPHLPAPI.@)
2655 * Get the table of active TCP connections.
2658 * pTcpTable [Out] buffer for TCP connections table
2659 * pdwSize [In/Out] length of output buffer
2660 * bOrder [In] whether to order the table
2664 * Failure: error code from winerror.h
2667 * If pdwSize is less than required, the function will return
2668 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to
2669 * the required byte size.
2670 * If bOrder is true, the returned table will be sorted, first by
2671 * local address and port number, then by remote address and port
2674 DWORD WINAPI
GetTcpTable(PMIB_TCPTABLE pTcpTable
, PDWORD pdwSize
, BOOL bOrder
)
2676 TRACE("pTcpTable %p, pdwSize %p, bOrder %d\n", pTcpTable
, pdwSize
, bOrder
);
2677 return GetExtendedTcpTable(pTcpTable
, pdwSize
, bOrder
, WS_AF_INET
, TCP_TABLE_BASIC_ALL
, 0);
2680 /******************************************************************
2681 * GetExtendedTcpTable (IPHLPAPI.@)
2683 DWORD WINAPI
GetExtendedTcpTable(PVOID pTcpTable
, PDWORD pdwSize
, BOOL bOrder
,
2684 ULONG ulAf
, TCP_TABLE_CLASS TableClass
, ULONG Reserved
)
2689 TRACE("pTcpTable %p, pdwSize %p, bOrder %d, ulAf %u, TableClass %u, Reserved %u\n",
2690 pTcpTable
, pdwSize
, bOrder
, ulAf
, TableClass
, Reserved
);
2692 if (!pdwSize
) return ERROR_INVALID_PARAMETER
;
2694 if (TableClass
>= TCP_TABLE_OWNER_MODULE_LISTENER
)
2695 FIXME("module classes not fully supported\n");
2700 ret
= build_tcp_table(TableClass
, &table
, bOrder
, GetProcessHeap(), 0, &size
);
2704 ret
= build_tcp6_table(TableClass
, &table
, bOrder
, GetProcessHeap(), 0, &size
);
2708 FIXME("ulAf = %u not supported\n", ulAf
);
2709 ret
= ERROR_NOT_SUPPORTED
;
2715 if (!pTcpTable
|| *pdwSize
< size
)
2718 ret
= ERROR_INSUFFICIENT_BUFFER
;
2723 memcpy(pTcpTable
, table
, size
);
2725 HeapFree(GetProcessHeap(), 0, table
);
2729 /******************************************************************
2730 * GetUdpTable (IPHLPAPI.@)
2732 * Get a table of active UDP connections.
2735 * pUdpTable [Out] buffer for UDP connections table
2736 * pdwSize [In/Out] length of output buffer
2737 * bOrder [In] whether to order the table
2741 * Failure: error code from winerror.h
2744 * If pdwSize is less than required, the function will return
2745 * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to the
2746 * required byte size.
2747 * If bOrder is true, the returned table will be sorted, first by
2748 * local address, then by local port number.
2750 DWORD WINAPI
GetUdpTable(PMIB_UDPTABLE pUdpTable
, PDWORD pdwSize
, BOOL bOrder
)
2752 return GetExtendedUdpTable(pUdpTable
, pdwSize
, bOrder
, WS_AF_INET
, UDP_TABLE_BASIC
, 0);
2755 /******************************************************************
2756 * GetUdp6Table (IPHLPAPI.@)
2758 DWORD WINAPI
GetUdp6Table(PMIB_UDP6TABLE pUdpTable
, PDWORD pdwSize
, BOOL bOrder
)
2760 return GetExtendedUdpTable(pUdpTable
, pdwSize
, bOrder
, WS_AF_INET6
, UDP_TABLE_BASIC
, 0);
2763 /******************************************************************
2764 * GetExtendedUdpTable (IPHLPAPI.@)
2766 DWORD WINAPI
GetExtendedUdpTable(PVOID pUdpTable
, PDWORD pdwSize
, BOOL bOrder
,
2767 ULONG ulAf
, UDP_TABLE_CLASS TableClass
, ULONG Reserved
)
2772 TRACE("pUdpTable %p, pdwSize %p, bOrder %d, ulAf %u, TableClass %u, Reserved %u\n",
2773 pUdpTable
, pdwSize
, bOrder
, ulAf
, TableClass
, Reserved
);
2775 if (!pdwSize
) return ERROR_INVALID_PARAMETER
;
2777 if (TableClass
== UDP_TABLE_OWNER_MODULE
)
2778 FIXME("UDP_TABLE_OWNER_MODULE not fully supported\n");
2783 ret
= build_udp_table(TableClass
, &table
, bOrder
, GetProcessHeap(), 0, &size
);
2787 ret
= build_udp6_table(TableClass
, &table
, bOrder
, GetProcessHeap(), 0, &size
);
2791 FIXME("ulAf = %u not supported\n", ulAf
);
2792 ret
= ERROR_NOT_SUPPORTED
;
2798 if (!pUdpTable
|| *pdwSize
< size
)
2801 ret
= ERROR_INSUFFICIENT_BUFFER
;
2806 memcpy(pUdpTable
, table
, size
);
2808 HeapFree(GetProcessHeap(), 0, table
);
2812 static void unicast_row_fill( MIB_UNICASTIPADDRESS_ROW
*row
, USHORT fam
, void *key
, struct nsi_ip_unicast_rw
*rw
,
2813 struct nsi_ip_unicast_dynamic
*dyn
, struct nsi_ip_unicast_static
*stat
)
2815 struct nsi_ipv4_unicast_key
*key4
= (struct nsi_ipv4_unicast_key
*)key
;
2816 struct nsi_ipv6_unicast_key
*key6
= (struct nsi_ipv6_unicast_key
*)key
;
2818 if (fam
== WS_AF_INET
)
2820 row
->Address
.Ipv4
.sin_family
= fam
;
2821 row
->Address
.Ipv4
.sin_port
= 0;
2822 row
->Address
.Ipv4
.sin_addr
= key4
->addr
;
2823 memset( row
->Address
.Ipv4
.sin_zero
, 0, sizeof(row
->Address
.Ipv4
.sin_zero
) );
2824 row
->InterfaceLuid
.Value
= key4
->luid
.Value
;
2828 row
->Address
.Ipv6
.sin6_family
= fam
;
2829 row
->Address
.Ipv6
.sin6_port
= 0;
2830 row
->Address
.Ipv6
.sin6_flowinfo
= 0;
2831 row
->Address
.Ipv6
.sin6_addr
= key6
->addr
;
2832 row
->Address
.Ipv6
.sin6_scope_id
= dyn
->scope_id
;
2833 row
->InterfaceLuid
.Value
= key6
->luid
.Value
;
2836 ConvertInterfaceLuidToIndex( &row
->InterfaceLuid
, &row
->InterfaceIndex
);
2837 row
->PrefixOrigin
= rw
->prefix_origin
;
2838 row
->SuffixOrigin
= rw
->suffix_origin
;
2839 row
->ValidLifetime
= rw
->valid_lifetime
;
2840 row
->PreferredLifetime
= rw
->preferred_lifetime
;
2841 row
->OnLinkPrefixLength
= rw
->on_link_prefix
;
2842 row
->SkipAsSource
= 0;
2843 row
->DadState
= dyn
->dad_state
;
2844 row
->ScopeId
.u
.Value
= dyn
->scope_id
;
2845 row
->CreationTimeStamp
.QuadPart
= stat
->creation_time
;
2848 DWORD WINAPI
GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW
*row
)
2850 struct nsi_ipv4_unicast_key key4
;
2851 struct nsi_ipv6_unicast_key key6
;
2852 struct nsi_ip_unicast_rw rw
;
2853 struct nsi_ip_unicast_dynamic dyn
;
2854 struct nsi_ip_unicast_static stat
;
2855 const NPI_MODULEID
*mod
;
2856 DWORD err
, key_size
;
2859 TRACE( "%p\n", row
);
2861 if (!row
) return ERROR_INVALID_PARAMETER
;
2862 mod
= ip_module_id( row
->Address
.si_family
);
2863 if (!mod
) return ERROR_INVALID_PARAMETER
;
2865 if (!row
->InterfaceLuid
.Value
)
2867 err
= ConvertInterfaceIndexToLuid( row
->InterfaceIndex
, &row
->InterfaceLuid
);
2868 if (err
) return err
;
2871 if (row
->Address
.si_family
== WS_AF_INET
)
2873 key4
.luid
= row
->InterfaceLuid
;
2874 key4
.addr
= row
->Address
.Ipv4
.sin_addr
;
2877 key_size
= sizeof(key4
);
2879 else if (row
->Address
.si_family
== WS_AF_INET6
)
2881 key6
.luid
= row
->InterfaceLuid
;
2882 key6
.addr
= row
->Address
.Ipv6
.sin6_addr
;
2884 key_size
= sizeof(key6
);
2886 else return ERROR_INVALID_PARAMETER
;
2888 err
= NsiGetAllParameters( 1, mod
, NSI_IP_UNICAST_TABLE
, key
, key_size
, &rw
, sizeof(rw
),
2889 &dyn
, sizeof(dyn
), &stat
, sizeof(stat
) );
2890 if (!err
) unicast_row_fill( row
, row
->Address
.si_family
, key
, &rw
, &dyn
, &stat
);
2894 DWORD WINAPI
GetUnicastIpAddressTable(ADDRESS_FAMILY family
, MIB_UNICASTIPADDRESS_TABLE
**table
)
2896 void *key
[2] = { NULL
, NULL
};
2897 struct nsi_ip_unicast_rw
*rw
[2] = { NULL
, NULL
};
2898 struct nsi_ip_unicast_dynamic
*dyn
[2] = { NULL
, NULL
};
2899 struct nsi_ip_unicast_static
*stat
[2] = { NULL
, NULL
};
2900 static const USHORT fam
[2] = { WS_AF_INET
, WS_AF_INET6
};
2901 static const DWORD key_size
[2] = { sizeof(struct nsi_ipv4_unicast_key
), sizeof(struct nsi_ipv6_unicast_key
) };
2902 DWORD err
, i
, size
, count
[2] = { 0, 0 };
2904 TRACE( "%u, %p\n", family
, table
);
2906 if (!table
|| (family
!= WS_AF_INET
&& family
!= WS_AF_INET6
&& family
!= WS_AF_UNSPEC
))
2907 return ERROR_INVALID_PARAMETER
;
2909 for (i
= 0; i
< 2; i
++)
2911 if (family
!= WS_AF_UNSPEC
&& family
!= fam
[i
]) continue;
2913 err
= NsiAllocateAndGetTable( 1, ip_module_id( fam
[i
] ), NSI_IP_UNICAST_TABLE
, key
+ i
, key_size
[i
],
2914 (void **)rw
+ i
, sizeof(**rw
), (void **)dyn
+ i
, sizeof(**dyn
),
2915 (void **)stat
+ i
, sizeof(**stat
), count
+ i
, 0 );
2919 size
= FIELD_OFFSET(MIB_UNICASTIPADDRESS_TABLE
, Table
[ count
[0] + count
[1] ]);
2920 *table
= heap_alloc( size
);
2923 err
= ERROR_NOT_ENOUGH_MEMORY
;
2927 (*table
)->NumEntries
= count
[0] + count
[1];
2928 for (i
= 0; i
< count
[0]; i
++)
2930 MIB_UNICASTIPADDRESS_ROW
*row
= (*table
)->Table
+ i
;
2931 struct nsi_ipv4_unicast_key
*key4
= (struct nsi_ipv4_unicast_key
*)key
[0];
2933 unicast_row_fill( row
, fam
[0], (void *)(key4
+ i
), rw
[0] + i
, dyn
[0] + i
, stat
[0] + i
);
2936 for (i
= 0; i
< count
[1]; i
++)
2938 MIB_UNICASTIPADDRESS_ROW
*row
= (*table
)->Table
+ count
[0] + i
;
2939 struct nsi_ipv6_unicast_key
*key6
= (struct nsi_ipv6_unicast_key
*)key
[1];
2941 unicast_row_fill( row
, fam
[1], (void *)(key6
+ i
), rw
[1] + i
, dyn
[1] + i
, stat
[1] + i
);
2945 for (i
= 0; i
< 2; i
++) NsiFreeTable( key
[i
], rw
[i
], dyn
[i
], stat
[i
] );
2949 /******************************************************************
2950 * GetUniDirectionalAdapterInfo (IPHLPAPI.@)
2952 * This is a Win98-only function to get information on "unidirectional"
2953 * adapters. Since this is pretty nonsensical in other contexts, it
2954 * never returns anything.
2957 * pIPIfInfo [Out] buffer for adapter infos
2958 * dwOutBufLen [Out] length of the output buffer
2962 * Failure: error code from winerror.h
2965 * Stub, returns ERROR_NOT_SUPPORTED.
2967 DWORD WINAPI
GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo
, PULONG dwOutBufLen
)
2969 TRACE("pIPIfInfo %p, dwOutBufLen %p\n", pIPIfInfo
, dwOutBufLen
);
2970 /* a unidirectional adapter?? not bloody likely! */
2971 return ERROR_NOT_SUPPORTED
;
2975 /******************************************************************
2976 * IpReleaseAddress (IPHLPAPI.@)
2978 * Release an IP obtained through DHCP,
2981 * AdapterInfo [In] adapter to release IP address
2985 * Failure: error code from winerror.h
2988 * Since GetAdaptersInfo never returns adapters that have DHCP enabled,
2989 * this function does nothing.
2992 * Stub, returns ERROR_NOT_SUPPORTED.
2994 DWORD WINAPI
IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo
)
2996 FIXME("Stub AdapterInfo %p\n", AdapterInfo
);
2997 return ERROR_NOT_SUPPORTED
;
3001 /******************************************************************
3002 * IpRenewAddress (IPHLPAPI.@)
3004 * Renew an IP obtained through DHCP.
3007 * AdapterInfo [In] adapter to renew IP address
3011 * Failure: error code from winerror.h
3014 * Since GetAdaptersInfo never returns adapters that have DHCP enabled,
3015 * this function does nothing.
3018 * Stub, returns ERROR_NOT_SUPPORTED.
3020 DWORD WINAPI
IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo
)
3022 FIXME("Stub AdapterInfo %p\n", AdapterInfo
);
3023 return ERROR_NOT_SUPPORTED
;
3027 /******************************************************************
3028 * NotifyAddrChange (IPHLPAPI.@)
3030 * Notify caller whenever the ip-interface map is changed.
3033 * Handle [Out] handle usable in asynchronous notification
3034 * overlapped [In] overlapped structure that notifies the caller
3038 * Failure: error code from winerror.h
3041 * Stub, returns ERROR_NOT_SUPPORTED.
3043 DWORD WINAPI
NotifyAddrChange(PHANDLE Handle
, LPOVERLAPPED overlapped
)
3045 FIXME("(Handle %p, overlapped %p): stub\n", Handle
, overlapped
);
3046 if (Handle
) *Handle
= INVALID_HANDLE_VALUE
;
3047 if (overlapped
) ((IO_STATUS_BLOCK
*) overlapped
)->u
.Status
= STATUS_PENDING
;
3048 return ERROR_IO_PENDING
;
3052 /******************************************************************
3053 * NotifyIpInterfaceChange (IPHLPAPI.@)
3055 DWORD WINAPI
NotifyIpInterfaceChange(ADDRESS_FAMILY family
, PIPINTERFACE_CHANGE_CALLBACK callback
,
3056 PVOID context
, BOOLEAN init_notify
, PHANDLE handle
)
3058 FIXME("(family %d, callback %p, context %p, init_notify %d, handle %p): stub\n",
3059 family
, callback
, context
, init_notify
, handle
);
3060 if (handle
) *handle
= NULL
;
3064 /******************************************************************
3065 * NotifyRouteChange2 (IPHLPAPI.@)
3067 DWORD WINAPI
NotifyRouteChange2(ADDRESS_FAMILY family
, PIPFORWARD_CHANGE_CALLBACK callback
, VOID
* context
,
3068 BOOLEAN init_notify
, HANDLE
* handle
)
3070 FIXME("(family %d, callback %p, context %p, init_notify %d, handle %p): stub\n",
3071 family
, callback
, context
, init_notify
, handle
);
3072 if (handle
) *handle
= NULL
;
3077 /******************************************************************
3078 * NotifyRouteChange (IPHLPAPI.@)
3080 * Notify caller whenever the ip routing table is changed.
3083 * Handle [Out] handle usable in asynchronous notification
3084 * overlapped [In] overlapped structure that notifies the caller
3088 * Failure: error code from winerror.h
3091 * Stub, returns ERROR_NOT_SUPPORTED.
3093 DWORD WINAPI
NotifyRouteChange(PHANDLE Handle
, LPOVERLAPPED overlapped
)
3095 FIXME("(Handle %p, overlapped %p): stub\n", Handle
, overlapped
);
3096 return ERROR_NOT_SUPPORTED
;
3100 /******************************************************************
3101 * NotifyUnicastIpAddressChange (IPHLPAPI.@)
3103 DWORD WINAPI
NotifyUnicastIpAddressChange(ADDRESS_FAMILY family
, PUNICAST_IPADDRESS_CHANGE_CALLBACK callback
,
3104 PVOID context
, BOOLEAN init_notify
, PHANDLE handle
)
3106 FIXME("(family %d, callback %p, context %p, init_notify %d, handle %p): semi-stub\n",
3107 family
, callback
, context
, init_notify
, handle
);
3108 if (handle
) *handle
= NULL
;
3111 callback(context
, NULL
, MibInitialNotification
);
3116 /******************************************************************
3117 * SendARP (IPHLPAPI.@)
3119 * Send an ARP request.
3122 * DestIP [In] attempt to obtain this IP
3123 * SrcIP [In] optional sender IP address
3124 * pMacAddr [Out] buffer for the mac address
3125 * PhyAddrLen [In/Out] length of the output buffer
3129 * Failure: error code from winerror.h
3132 * Stub, returns ERROR_NOT_SUPPORTED.
3134 DWORD WINAPI
SendARP(IPAddr DestIP
, IPAddr SrcIP
, PULONG pMacAddr
, PULONG PhyAddrLen
)
3136 FIXME("(DestIP 0x%08x, SrcIP 0x%08x, pMacAddr %p, PhyAddrLen %p): stub\n",
3137 DestIP
, SrcIP
, pMacAddr
, PhyAddrLen
);
3138 return ERROR_NOT_SUPPORTED
;
3142 /******************************************************************
3143 * SetIfEntry (IPHLPAPI.@)
3145 * Set the administrative status of an interface.
3148 * pIfRow [In] dwAdminStatus member specifies the new status.
3152 * Failure: error code from winerror.h
3155 * Stub, returns ERROR_NOT_SUPPORTED.
3157 DWORD WINAPI
SetIfEntry(PMIB_IFROW pIfRow
)
3159 FIXME("(pIfRow %p): stub\n", pIfRow
);
3160 /* this is supposed to set an interface administratively up or down.
3161 Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and
3162 this sort of down is indistinguishable from other sorts of down (e.g. no
3164 return ERROR_NOT_SUPPORTED
;
3168 /******************************************************************
3169 * SetIpForwardEntry (IPHLPAPI.@)
3171 * Modify an existing route.
3174 * pRoute [In] route with the new information
3178 * Failure: error code from winerror.h
3181 * Stub, returns NO_ERROR.
3183 DWORD WINAPI
SetIpForwardEntry(PMIB_IPFORWARDROW pRoute
)
3185 FIXME("(pRoute %p): stub\n", pRoute
);
3186 /* this is to add a route entry, how's it distinguishable from
3187 CreateIpForwardEntry?
3188 could use SIOCADDRT, not sure I want to */
3193 /******************************************************************
3194 * SetIpNetEntry (IPHLPAPI.@)
3196 * Modify an existing ARP entry.
3199 * pArpEntry [In] ARP entry with the new information
3203 * Failure: error code from winerror.h
3206 * Stub, returns NO_ERROR.
3208 DWORD WINAPI
SetIpNetEntry(PMIB_IPNETROW pArpEntry
)
3210 FIXME("(pArpEntry %p): stub\n", pArpEntry
);
3211 /* same as CreateIpNetEntry here, could use SIOCSARP, not sure I want to */
3216 /******************************************************************
3217 * SetIpStatistics (IPHLPAPI.@)
3219 * Toggle IP forwarding and det the default TTL value.
3222 * pIpStats [In] IP statistics with the new information
3226 * Failure: error code from winerror.h
3229 * Stub, returns NO_ERROR.
3231 DWORD WINAPI
SetIpStatistics(PMIB_IPSTATS pIpStats
)
3233 FIXME("(pIpStats %p): stub\n", pIpStats
);
3238 /******************************************************************
3239 * SetIpTTL (IPHLPAPI.@)
3241 * Set the default TTL value.
3244 * nTTL [In] new TTL value
3248 * Failure: error code from winerror.h
3251 * Stub, returns NO_ERROR.
3253 DWORD WINAPI
SetIpTTL(UINT nTTL
)
3255 FIXME("(nTTL %d): stub\n", nTTL
);
3256 /* could echo nTTL > /proc/net/sys/net/ipv4/ip_default_ttl, not sure I
3257 want to. Could map EACCESS to ERROR_ACCESS_DENIED, I suppose */
3262 /******************************************************************
3263 * SetTcpEntry (IPHLPAPI.@)
3265 * Set the state of a TCP connection.
3268 * pTcpRow [In] specifies connection with new state
3272 * Failure: error code from winerror.h
3275 * Stub, returns NO_ERROR.
3277 DWORD WINAPI
SetTcpEntry(PMIB_TCPROW pTcpRow
)
3279 FIXME("(pTcpRow %p): stub\n", pTcpRow
);
3283 /******************************************************************
3284 * SetPerTcpConnectionEStats (IPHLPAPI.@)
3286 DWORD WINAPI
SetPerTcpConnectionEStats(PMIB_TCPROW row
, TCP_ESTATS_TYPE state
, PBYTE rw
,
3287 ULONG version
, ULONG size
, ULONG offset
)
3289 FIXME("(row %p, state %d, rw %p, version %u, size %u, offset %u): stub\n",
3290 row
, state
, rw
, version
, size
, offset
);
3291 return ERROR_NOT_SUPPORTED
;
3295 /******************************************************************
3296 * UnenableRouter (IPHLPAPI.@)
3298 * Decrement the IP-forwarding reference count. Turn off IP-forwarding
3299 * if it reaches zero.
3302 * pOverlapped [In/Out] should be the same as in EnableRouter()
3303 * lpdwEnableCount [Out] optional, receives reference count
3307 * Failure: error code from winerror.h
3310 * Stub, returns ERROR_NOT_SUPPORTED.
3312 DWORD WINAPI
UnenableRouter(OVERLAPPED
* pOverlapped
, LPDWORD lpdwEnableCount
)
3314 FIXME("(pOverlapped %p, lpdwEnableCount %p): stub\n", pOverlapped
,
3316 /* could echo "0" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to
3317 could map EACCESS to ERROR_ACCESS_DENIED, I suppose
3319 return ERROR_NOT_SUPPORTED
;
3322 /******************************************************************
3323 * PfCreateInterface (IPHLPAPI.@)
3325 DWORD WINAPI
PfCreateInterface(DWORD dwName
, PFFORWARD_ACTION inAction
, PFFORWARD_ACTION outAction
,
3326 BOOL bUseLog
, BOOL bMustBeUnique
, INTERFACE_HANDLE
*ppInterface
)
3328 FIXME("(%d %d %d %x %x %p) stub\n", dwName
, inAction
, outAction
, bUseLog
, bMustBeUnique
, ppInterface
);
3329 return ERROR_CALL_NOT_IMPLEMENTED
;
3332 /******************************************************************
3333 * PfUnBindInterface (IPHLPAPI.@)
3335 DWORD WINAPI
PfUnBindInterface(INTERFACE_HANDLE interface
)
3337 FIXME("(%p) stub\n", interface
);
3338 return ERROR_CALL_NOT_IMPLEMENTED
;
3341 /******************************************************************
3342 * PfDeleteInterface(IPHLPAPI.@)
3344 DWORD WINAPI
PfDeleteInterface(INTERFACE_HANDLE interface
)
3346 FIXME("(%p) stub\n", interface
);
3347 return ERROR_CALL_NOT_IMPLEMENTED
;
3350 /******************************************************************
3351 * PfBindInterfaceToIPAddress(IPHLPAPI.@)
3353 DWORD WINAPI
PfBindInterfaceToIPAddress(INTERFACE_HANDLE interface
, PFADDRESSTYPE type
, PBYTE ip
)
3355 FIXME("(%p %d %p) stub\n", interface
, type
, ip
);
3356 return ERROR_CALL_NOT_IMPLEMENTED
;
3359 /******************************************************************
3360 * GetTcpTable2 (IPHLPAPI.@)
3362 ULONG WINAPI
GetTcpTable2(PMIB_TCPTABLE2 table
, PULONG size
, BOOL order
)
3364 FIXME("pTcpTable2 %p, pdwSize %p, bOrder %d: stub\n", table
, size
, order
);
3365 return ERROR_NOT_SUPPORTED
;
3368 /******************************************************************
3369 * GetTcp6Table (IPHLPAPI.@)
3371 ULONG WINAPI
GetTcp6Table(PMIB_TCP6TABLE table
, PULONG size
, BOOL order
)
3373 TRACE("(table %p, size %p, order %d)\n", table
, size
, order
);
3374 return GetExtendedTcpTable(table
, size
, order
, WS_AF_INET6
, TCP_TABLE_BASIC_ALL
, 0);
3377 /******************************************************************
3378 * GetTcp6Table2 (IPHLPAPI.@)
3380 ULONG WINAPI
GetTcp6Table2(PMIB_TCP6TABLE2 table
, PULONG size
, BOOL order
)
3382 FIXME("pTcp6Table2 %p, size %p, order %d: stub\n", table
, size
, order
);
3383 return ERROR_NOT_SUPPORTED
;
3386 /******************************************************************
3387 * ConvertInterfaceAliasToLuid (IPHLPAPI.@)
3389 DWORD WINAPI
ConvertInterfaceAliasToLuid( const WCHAR
*alias
, NET_LUID
*luid
)
3391 struct nsi_ndis_ifinfo_rw
*data
;
3392 DWORD err
, count
, i
, len
;
3395 TRACE( "(%s %p)\n", debugstr_w(alias
), luid
);
3397 if (!alias
|| !*alias
|| !luid
) return ERROR_INVALID_PARAMETER
;
3399 len
= strlenW( alias
);
3401 err
= NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, (void **)&keys
, sizeof(*keys
),
3402 (void **)&data
, sizeof(*data
), NULL
, 0, NULL
, 0, &count
, 0 );
3403 if (err
) return err
;
3405 err
= ERROR_INVALID_PARAMETER
;
3406 for (i
= 0; i
< count
; i
++)
3408 if (data
[i
].alias
.Length
== len
* 2 && !memcmp( data
[i
].alias
.String
, alias
, len
* 2 ))
3410 luid
->Value
= keys
[i
].Value
;
3411 err
= ERROR_SUCCESS
;
3415 NsiFreeTable( keys
, data
, NULL
, NULL
);
3419 /******************************************************************
3420 * ConvertInterfaceGuidToLuid (IPHLPAPI.@)
3422 DWORD WINAPI
ConvertInterfaceGuidToLuid(const GUID
*guid
, NET_LUID
*luid
)
3424 struct nsi_ndis_ifinfo_static
*data
;
3425 DWORD err
, count
, i
;
3428 TRACE( "(%s %p)\n", debugstr_guid(guid
), luid
);
3430 if (!guid
|| !luid
) return ERROR_INVALID_PARAMETER
;
3433 err
= NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, (void **)&keys
, sizeof(*keys
),
3434 NULL
, 0, NULL
, 0, (void **)&data
, sizeof(*data
), &count
, 0 );
3435 if (err
) return err
;
3437 err
= ERROR_INVALID_PARAMETER
;
3438 for (i
= 0; i
< count
; i
++)
3440 if (IsEqualGUID( &data
[i
].if_guid
, guid
))
3442 luid
->Value
= keys
[i
].Value
;
3443 err
= ERROR_SUCCESS
;
3447 NsiFreeTable( keys
, NULL
, NULL
, data
);
3451 /******************************************************************
3452 * ConvertInterfaceIndexToLuid (IPHLPAPI.@)
3454 DWORD WINAPI
ConvertInterfaceIndexToLuid(NET_IFINDEX index
, NET_LUID
*luid
)
3458 TRACE( "(%u %p)\n", index
, luid
);
3460 if (!luid
) return ERROR_INVALID_PARAMETER
;
3462 err
= NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_INDEX_LUID_TABLE
, &index
, sizeof(index
),
3463 NSI_PARAM_TYPE_STATIC
, luid
, sizeof(*luid
), 0 );
3464 if (err
) luid
->Value
= 0;
3468 /******************************************************************
3469 * ConvertInterfaceLuidToAlias (IPHLPAPI.@)
3471 DWORD WINAPI
ConvertInterfaceLuidToAlias( const NET_LUID
*luid
, WCHAR
*alias
, SIZE_T len
)
3474 IF_COUNTED_STRING name
;
3476 TRACE( "(%p %p %u)\n", luid
, alias
, (DWORD
)len
);
3478 if (!luid
|| !alias
) return ERROR_INVALID_PARAMETER
;
3480 err
= NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, luid
, sizeof(*luid
),
3481 NSI_PARAM_TYPE_RW
, &name
, sizeof(name
),
3482 FIELD_OFFSET(struct nsi_ndis_ifinfo_rw
, alias
) );
3483 if (err
) return err
;
3485 if (len
<= name
.Length
/ sizeof(WCHAR
)) return ERROR_NOT_ENOUGH_MEMORY
;
3486 memcpy( alias
, name
.String
, name
.Length
);
3487 alias
[name
.Length
/ sizeof(WCHAR
)] = '\0';
3492 /******************************************************************
3493 * ConvertInterfaceLuidToGuid (IPHLPAPI.@)
3495 DWORD WINAPI
ConvertInterfaceLuidToGuid(const NET_LUID
*luid
, GUID
*guid
)
3499 TRACE( "(%p %p)\n", luid
, guid
);
3501 if (!luid
|| !guid
) return ERROR_INVALID_PARAMETER
;
3503 err
= NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, luid
, sizeof(*luid
),
3504 NSI_PARAM_TYPE_STATIC
, guid
, sizeof(*guid
),
3505 FIELD_OFFSET(struct nsi_ndis_ifinfo_static
, if_guid
) );
3506 if (err
) memset( guid
, 0, sizeof(*guid
) );
3510 /******************************************************************
3511 * ConvertInterfaceLuidToIndex (IPHLPAPI.@)
3513 DWORD WINAPI
ConvertInterfaceLuidToIndex(const NET_LUID
*luid
, NET_IFINDEX
*index
)
3517 TRACE( "(%p %p)\n", luid
, index
);
3519 if (!luid
|| !index
) return ERROR_INVALID_PARAMETER
;
3521 err
= NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID
, NSI_NDIS_IFINFO_TABLE
, luid
, sizeof(*luid
),
3522 NSI_PARAM_TYPE_STATIC
, index
, sizeof(*index
),
3523 FIELD_OFFSET(struct nsi_ndis_ifinfo_static
, if_index
) );
3524 if (err
) *index
= 0;
3528 /******************************************************************
3529 * ConvertInterfaceLuidToNameA (IPHLPAPI.@)
3531 DWORD WINAPI
ConvertInterfaceLuidToNameA(const NET_LUID
*luid
, char *name
, SIZE_T len
)
3534 WCHAR nameW
[IF_MAX_STRING_SIZE
+ 1];
3536 TRACE( "(%p %p %u)\n", luid
, name
, (DWORD
)len
);
3538 if (!luid
) return ERROR_INVALID_PARAMETER
;
3539 if (!name
|| !len
) return ERROR_NOT_ENOUGH_MEMORY
;
3541 err
= ConvertInterfaceLuidToNameW( luid
, nameW
, ARRAY_SIZE(nameW
) );
3542 if (err
) return err
;
3544 if (!WideCharToMultiByte( CP_UNIXCP
, 0, nameW
, -1, name
, len
, NULL
, NULL
))
3545 err
= GetLastError();
3549 static const WCHAR otherW
[] = {'o','t','h','e','r',0};
3550 static const WCHAR ethernetW
[] = {'e','t','h','e','r','n','e','t',0};
3551 static const WCHAR tokenringW
[] = {'t','o','k','e','n','r','i','n','g',0};
3552 static const WCHAR pppW
[] = {'p','p','p',0};
3553 static const WCHAR loopbackW
[] = {'l','o','o','p','b','a','c','k',0};
3554 static const WCHAR atmW
[] = {'a','t','m',0};
3555 static const WCHAR wirelessW
[] = {'w','i','r','e','l','e','s','s',0};
3556 static const WCHAR tunnelW
[] = {'t','u','n','n','e','l',0};
3557 static const WCHAR ieee1394W
[] = {'i','e','e','e','1','3','9','4',0};
3561 const WCHAR
*prefix
;
3564 static const struct name_prefix name_prefixes
[] =
3566 { otherW
, IF_TYPE_OTHER
},
3567 { ethernetW
, IF_TYPE_ETHERNET_CSMACD
},
3568 { tokenringW
, IF_TYPE_ISO88025_TOKENRING
},
3569 { pppW
, IF_TYPE_PPP
},
3570 { loopbackW
, IF_TYPE_SOFTWARE_LOOPBACK
},
3571 { atmW
, IF_TYPE_ATM
},
3572 { wirelessW
, IF_TYPE_IEEE80211
},
3573 { tunnelW
, IF_TYPE_TUNNEL
},
3574 { ieee1394W
, IF_TYPE_IEEE1394
}
3577 /******************************************************************
3578 * ConvertInterfaceLuidToNameW (IPHLPAPI.@)
3580 DWORD WINAPI
ConvertInterfaceLuidToNameW(const NET_LUID
*luid
, WCHAR
*name
, SIZE_T len
)
3583 const WCHAR
*prefix
= NULL
;
3584 WCHAR buf
[IF_MAX_STRING_SIZE
+ 1];
3585 static const WCHAR prefix_fmt
[] = {'%','s','_','%','d',0};
3586 static const WCHAR unk_fmt
[] = {'i','f','t','y','p','e','%','d','_','%','d',0};
3588 TRACE( "(%p %p %u)\n", luid
, name
, (DWORD
)len
);
3590 if (!luid
|| !name
) return ERROR_INVALID_PARAMETER
;
3592 for (i
= 0; i
< ARRAY_SIZE(name_prefixes
); i
++)
3594 if (luid
->Info
.IfType
== name_prefixes
[i
].type
)
3596 prefix
= name_prefixes
[i
].prefix
;
3601 if (prefix
) needed
= snprintfW( buf
, len
, prefix_fmt
, prefix
, luid
->Info
.NetLuidIndex
);
3602 else needed
= snprintfW( buf
, len
, unk_fmt
, luid
->Info
.IfType
, luid
->Info
.NetLuidIndex
);
3604 if (needed
>= len
) return ERROR_NOT_ENOUGH_MEMORY
;
3605 memcpy( name
, buf
, (needed
+ 1) * sizeof(WCHAR
) );
3606 return ERROR_SUCCESS
;
3609 /******************************************************************
3610 * ConvertInterfaceNameToLuidA (IPHLPAPI.@)
3612 DWORD WINAPI
ConvertInterfaceNameToLuidA(const char *name
, NET_LUID
*luid
)
3614 WCHAR nameW
[IF_MAX_STRING_SIZE
];
3616 TRACE( "(%s %p)\n", debugstr_a(name
), luid
);
3618 if (!name
) return ERROR_INVALID_NAME
;
3619 if (!MultiByteToWideChar( CP_UNIXCP
, 0, name
, -1, nameW
, ARRAY_SIZE(nameW
) ))
3620 return GetLastError();
3622 return ConvertInterfaceNameToLuidW( nameW
, luid
);
3625 /******************************************************************
3626 * ConvertInterfaceNameToLuidW (IPHLPAPI.@)
3628 DWORD WINAPI
ConvertInterfaceNameToLuidW(const WCHAR
*name
, NET_LUID
*luid
)
3631 static const WCHAR iftype
[] = {'i','f','t','y','p','e',0};
3632 DWORD type
= ~0u, i
;
3633 WCHAR buf
[IF_MAX_STRING_SIZE
+ 1];
3635 TRACE( "(%s %p)\n", debugstr_w(name
), luid
);
3637 if (!luid
) return ERROR_INVALID_PARAMETER
;
3638 memset( luid
, 0, sizeof(*luid
) );
3640 if (!name
|| !(sep
= strchrW( name
, '_' )) || sep
>= name
+ ARRAY_SIZE(buf
)) return ERROR_INVALID_NAME
;
3641 memcpy( buf
, name
, (sep
- name
) * sizeof(WCHAR
) );
3642 buf
[sep
- name
] = '\0';
3644 if (sep
- name
> ARRAY_SIZE(iftype
) - 1 && !memcmp( buf
, iftype
, (ARRAY_SIZE(iftype
) - 1) * sizeof(WCHAR
) ))
3646 type
= atoiW( buf
+ ARRAY_SIZE(iftype
) - 1 );
3650 for (i
= 0; i
< ARRAY_SIZE(name_prefixes
); i
++)
3652 if (!strcmpW( buf
, name_prefixes
[i
].prefix
))
3654 type
= name_prefixes
[i
].type
;
3659 if (type
== ~0u) return ERROR_INVALID_NAME
;
3661 luid
->Info
.NetLuidIndex
= atoiW( sep
+ 1 );
3662 luid
->Info
.IfType
= type
;
3663 return ERROR_SUCCESS
;
3666 /******************************************************************
3667 * ConvertLengthToIpv4Mask (IPHLPAPI.@)
3669 DWORD WINAPI
ConvertLengthToIpv4Mask(ULONG mask_len
, ULONG
*mask
)
3673 *mask
= INADDR_NONE
;
3674 return ERROR_INVALID_PARAMETER
;
3680 *mask
= htonl(~0u << (32 - mask_len
));
3685 /******************************************************************
3686 * if_nametoindex (IPHLPAPI.@)
3688 IF_INDEX WINAPI
IPHLP_if_nametoindex(const char *name
)
3694 TRACE( "(%s)\n", name
);
3696 err
= ConvertInterfaceNameToLuidA( name
, &luid
);
3699 err
= ConvertInterfaceLuidToIndex( &luid
, &index
);
3704 /******************************************************************
3705 * if_indextoname (IPHLPAPI.@)
3707 char *WINAPI
IPHLP_if_indextoname( NET_IFINDEX index
, char *name
)
3712 TRACE( "(%u, %p)\n", index
, name
);
3714 err
= ConvertInterfaceIndexToLuid( index
, &luid
);
3715 if (err
) return NULL
;
3717 err
= ConvertInterfaceLuidToNameA( &luid
, name
, IF_MAX_STRING_SIZE
);
3718 if (err
) return NULL
;
3722 /******************************************************************
3723 * GetIpInterfaceTable (IPHLPAPI.@)
3725 DWORD WINAPI
GetIpInterfaceTable(ADDRESS_FAMILY family
, PMIB_IPINTERFACE_TABLE
*table
)
3727 FIXME("(%u %p): stub\n", family
, table
);
3728 return ERROR_NOT_SUPPORTED
;
3731 /******************************************************************
3732 * GetBestRoute2 (IPHLPAPI.@)
3734 DWORD WINAPI
GetBestRoute2(NET_LUID
*luid
, NET_IFINDEX index
,
3735 const SOCKADDR_INET
*source
, const SOCKADDR_INET
*destination
,
3736 ULONG options
, PMIB_IPFORWARD_ROW2 bestroute
,
3737 SOCKADDR_INET
*bestaddress
)
3742 FIXME("(%p, %d, %p, %p, 0x%08x, %p, %p): stub\n", luid
, index
, source
,
3743 destination
, options
, bestroute
, bestaddress
);
3745 if (!destination
|| !bestroute
|| !bestaddress
)
3746 return ERROR_INVALID_PARAMETER
;
3748 return ERROR_NOT_SUPPORTED
;
3751 /******************************************************************
3752 * ParseNetworkString (IPHLPAPI.@)
3754 DWORD WINAPI
ParseNetworkString(const WCHAR
*str
, DWORD type
,
3755 NET_ADDRESS_INFO
*info
, USHORT
*port
, BYTE
*prefix_len
)
3758 IN6_ADDR temp_addr6
;
3760 USHORT temp_port
= 0;
3763 TRACE("(%s, %d, %p, %p, %p)\n", debugstr_w(str
), type
, info
, port
, prefix_len
);
3766 return ERROR_INVALID_PARAMETER
;
3768 if (type
& NET_STRING_IPV4_ADDRESS
)
3770 status
= RtlIpv4StringToAddressExW(str
, TRUE
, &temp_addr4
, &temp_port
);
3771 if (SUCCEEDED(status
) && !temp_port
)
3775 info
->Format
= NET_ADDRESS_IPV4
;
3776 info
->u
.Ipv4Address
.sin_addr
= temp_addr4
;
3777 info
->u
.Ipv4Address
.sin_port
= 0;
3779 if (port
) *port
= 0;
3780 if (prefix_len
) *prefix_len
= 255;
3781 return ERROR_SUCCESS
;
3784 if (type
& NET_STRING_IPV4_SERVICE
)
3786 status
= RtlIpv4StringToAddressExW(str
, TRUE
, &temp_addr4
, &temp_port
);
3787 if (SUCCEEDED(status
) && temp_port
)
3791 info
->Format
= NET_ADDRESS_IPV4
;
3792 info
->u
.Ipv4Address
.sin_addr
= temp_addr4
;
3793 info
->u
.Ipv4Address
.sin_port
= temp_port
;
3795 if (port
) *port
= ntohs(temp_port
);
3796 if (prefix_len
) *prefix_len
= 255;
3797 return ERROR_SUCCESS
;
3800 if (type
& NET_STRING_IPV6_ADDRESS
)
3802 status
= RtlIpv6StringToAddressExW(str
, &temp_addr6
, &temp_scope
, &temp_port
);
3803 if (SUCCEEDED(status
) && !temp_port
)
3807 info
->Format
= NET_ADDRESS_IPV6
;
3808 info
->u
.Ipv6Address
.sin6_addr
= temp_addr6
;
3809 info
->u
.Ipv6Address
.sin6_scope_id
= temp_scope
;
3810 info
->u
.Ipv6Address
.sin6_port
= 0;
3812 if (port
) *port
= 0;
3813 if (prefix_len
) *prefix_len
= 255;
3814 return ERROR_SUCCESS
;
3817 if (type
& NET_STRING_IPV6_SERVICE
)
3819 status
= RtlIpv6StringToAddressExW(str
, &temp_addr6
, &temp_scope
, &temp_port
);
3820 if (SUCCEEDED(status
) && temp_port
)
3824 info
->Format
= NET_ADDRESS_IPV6
;
3825 info
->u
.Ipv6Address
.sin6_addr
= temp_addr6
;
3826 info
->u
.Ipv6Address
.sin6_scope_id
= temp_scope
;
3827 info
->u
.Ipv6Address
.sin6_port
= temp_port
;
3829 if (port
) *port
= ntohs(temp_port
);
3830 if (prefix_len
) *prefix_len
= 255;
3831 return ERROR_SUCCESS
;
3835 if (info
) info
->Format
= NET_ADDRESS_FORMAT_UNSPECIFIED
;
3837 if (type
& ~(NET_STRING_IPV4_ADDRESS
|NET_STRING_IPV4_SERVICE
|NET_STRING_IPV6_ADDRESS
|NET_STRING_IPV6_SERVICE
))
3839 FIXME("Unimplemented type 0x%x\n", type
);
3840 return ERROR_NOT_SUPPORTED
;
3843 return ERROR_INVALID_PARAMETER
;