1 /* Copyright (C) 2003 Art Yerkes
2 * A reimplementation of ifenum.c by Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Implementation notes
19 * - Our bretheren use IOCTL_TCP_QUERY_INFORMATION_EX to get information
20 * from tcpip.sys and IOCTL_TCP_SET_INFORMATION_EX to set info (such as
21 * the route table). These ioctls mirror WsControl exactly in usage.
22 * - This iphlpapi does not rely on any reactos-only features.
23 * - This implementation is meant to be largely correct. I am not, however,
24 * paying any attention to performance. It can be done faster, and
25 * someone should definately optimize this code when speed is more of a
26 * priority than it is now.
28 * Edited implementation notes from the original -- Basically edited to add
29 * information and prune things which are not accurate about this file.
30 * Interface index fun:
31 * - Windows may rely on an index being cleared in the topmost 8 bits in some
32 * APIs; see GetFriendlyIfIndex and the mention of "backward compatible"
33 * indexes. It isn't clear which APIs might fail with non-backward-compatible
34 * indexes, but I'll keep them bits clear just in case.
36 * - We don't support IPv6 addresses here yet -- I moved the upper edge
37 * functions into iphlpv6.c (arty)
39 #include "iphlpapi_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi
);
49 const PWCHAR TcpFileName
= L
"\\Device\\Tcp";
53 /* I'm a bit skittish about maintaining this info in memory, as I'd rather
54 * not add any mutex or critical section blockers to these functions. I've
55 * encountered far too many windows functions that contribute to deadlock
56 * by not announcing themselves. */
57 void interfaceMapInit(void)
59 /* For now, nothing */
62 void interfaceMapFree(void)
67 NTSTATUS
openTcpFile(PHANDLE tcpFile
) {
68 UNICODE_STRING fileName
;
69 OBJECT_ATTRIBUTES objectAttributes
;
70 IO_STATUS_BLOCK ioStatusBlock
;
75 /* Shamelessly ripped from CreateFileW */
76 RtlInitUnicodeString( &fileName
, TcpFileName
);
78 InitializeObjectAttributes( &objectAttributes
,
84 status
= ZwCreateFile( tcpFile
,
85 SYNCHRONIZE
| GENERIC_EXECUTE
|
86 GENERIC_READ
| GENERIC_WRITE
,
90 FILE_ATTRIBUTE_NORMAL
,
91 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
93 FILE_SYNCHRONOUS_IO_NONALERT
,
97 /* String does not need to be freed: it points to the constant
98 * string we provided */
100 if (!NT_SUCCESS(status
)) {
101 ERR("openTcpFile for <%wZ> failed: 0x%lx\n", &fileName
, status
);
102 *tcpFile
= INVALID_HANDLE_VALUE
;
108 void closeTcpFile( HANDLE h
) {
110 ASSERT(h
!= INVALID_HANDLE_VALUE
);
114 /* A generic thing-getting function which interacts in the right way with
115 * TDI. This may seem oblique, but I'm using it to reduce code and hopefully
116 * make this thing easier to debug.
118 * The things returned can be any of:
126 NTSTATUS
tdiGetSetOfThings( HANDLE tcpFile
,
135 PDWORD numEntries
) {
136 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
138 NTSTATUS status
= STATUS_SUCCESS
;
139 DWORD allocationSizeForEntityArray
= entrySize
* MAX_TDI_ENTITIES
,
140 arraySize
= entrySize
* MAX_TDI_ENTITIES
;
142 TRACE("TdiGetSetOfThings(tcpFile %x,toiClass %x,toiType %x,toiId %x,"
143 "teiEntity %x,fixedPart %d,entrySize %d)\n",
152 req
.ID
.toi_class
= toiClass
;
153 req
.ID
.toi_type
= toiType
;
154 req
.ID
.toi_id
= toiId
;
155 req
.ID
.toi_entity
.tei_entity
= teiEntity
;
156 req
.ID
.toi_entity
.tei_instance
= teiInstance
;
158 /* There's a subtle problem here...
159 * If an interface is added at this exact instant, (as if by a PCMCIA
160 * card insertion), the array will still not have enough entries after
161 * have allocated it after the first DeviceIoControl call.
163 * We'll get around this by repeating until the number of interfaces
167 assert( !entitySet
); /* We must not have an entity set allocated */
168 status
= DeviceIoControl( tcpFile
,
169 IOCTL_TCP_QUERY_INFORMATION_EX
,
174 &allocationSizeForEntityArray
,
177 if(!NT_SUCCESS(status
))
179 ERR("IOCTL Failed\n");
180 return STATUS_UNSUCCESSFUL
;
183 arraySize
= allocationSizeForEntityArray
;
184 entitySet
= HeapAlloc( GetProcessHeap(), 0, arraySize
);
187 status
= STATUS_INSUFFICIENT_RESOURCES
;
188 WARN("TdiGetSetOfThings() => %08x\n", (int)status
);
192 status
= DeviceIoControl( tcpFile
,
193 IOCTL_TCP_QUERY_INFORMATION_EX
,
198 &allocationSizeForEntityArray
,
201 /* This is why we have the loop -- we might have added an adapter */
202 if( arraySize
== allocationSizeForEntityArray
)
205 HeapFree( GetProcessHeap(), 0, entitySet
);
210 WARN("IOCTL Failed\n");
211 return STATUS_UNSUCCESSFUL
;
214 WARN("TdiGetSetOfThings(): Array changed size: %d -> %d.\n",
215 arraySize
, allocationSizeForEntityArray
);
216 } while( TRUE
); /* We break if the array we received was the size we
217 * expected. Therefore, we got here because it wasn't */
219 *numEntries
= (arraySize
- fixedPart
) / entrySize
;
220 *tdiEntitySet
= entitySet
;
222 WARN("TdiGetSetOfThings() => Success: %d things @ %08x\n",
223 (int)*numEntries
, (int)entitySet
);
225 return STATUS_SUCCESS
;
228 VOID
tdiFreeThingSet( PVOID things
) {
229 HeapFree( GetProcessHeap(), 0, things
);
232 NTSTATUS tdiGetMibForIfEntity
233 ( HANDLE tcpFile
, TDIEntityID
*ent
, IFEntrySafelySized
*entry
) {
234 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
235 NTSTATUS status
= STATUS_SUCCESS
;
238 WARN("TdiGetMibForIfEntity(tcpFile %x,entityId %x)\n",
239 (int)tcpFile
, (int)ent
->tei_instance
);
241 req
.ID
.toi_class
= INFO_CLASS_PROTOCOL
;
242 req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
243 req
.ID
.toi_id
= IF_MIB_STATS_ID
;
244 req
.ID
.toi_entity
= *ent
;
246 status
= DeviceIoControl( tcpFile
,
247 IOCTL_TCP_QUERY_INFORMATION_EX
,
257 WARN("IOCTL Failed\n");
258 return STATUS_UNSUCCESSFUL
;
261 TRACE("TdiGetMibForIfEntity() => {\n"
262 " if_index ....................... %x\n"
263 " if_type ........................ %x\n"
264 " if_mtu ......................... %d\n"
265 " if_speed ....................... %x\n"
266 " if_physaddrlen ................. %d\n",
271 entry
->ent
.if_physaddrlen
);
272 TRACE(" if_physaddr .................... %02x:%02x:%02x:%02x:%02x:%02x\n"
273 " if_descr ....................... %s\n",
274 entry
->ent
.if_physaddr
[0] & 0xff,
275 entry
->ent
.if_physaddr
[1] & 0xff,
276 entry
->ent
.if_physaddr
[2] & 0xff,
277 entry
->ent
.if_physaddr
[3] & 0xff,
278 entry
->ent
.if_physaddr
[4] & 0xff,
279 entry
->ent
.if_physaddr
[5] & 0xff,
280 entry
->ent
.if_descr
);
281 TRACE("} status %08x\n",status
);
286 NTSTATUS
tdiGetEntityIDSet( HANDLE tcpFile
,
287 TDIEntityID
**entitySet
,
288 PDWORD numEntities
) {
289 NTSTATUS status
= tdiGetSetOfThings( tcpFile
,
299 if( NT_SUCCESS(status
) ) {
302 for( i
= 0; i
< *numEntities
; i
++ ) {
303 TRACE("%-4d: %04x:%08x\n",
305 (*entitySet
)[i
].tei_entity
,
306 (*entitySet
)[i
].tei_instance
);
313 BOOL
isInterface( TDIEntityID
*if_maybe
) {
315 if_maybe
->tei_entity
== IF_ENTITY
;
318 static BOOL
isLoopback( HANDLE tcpFile
, TDIEntityID
*loop_maybe
) {
319 IFEntrySafelySized entryInfo
;
322 status
= tdiGetMibForIfEntity( tcpFile
,
326 return NT_SUCCESS(status
) && (!entryInfo
.ent
.if_type
||
327 entryInfo
.ent
.if_type
== IFENT_SOFTWARE_LOOPBACK
);
330 NTSTATUS
tdiGetEntityType( HANDLE tcpFile
, TDIEntityID
*ent
, PULONG type
) {
331 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
332 NTSTATUS status
= STATUS_SUCCESS
;
335 TRACE("TdiGetEntityType(tcpFile %x,entityId %x)\n",
336 (DWORD
)tcpFile
, ent
->tei_instance
);
338 req
.ID
.toi_class
= INFO_CLASS_GENERIC
;
339 req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
340 req
.ID
.toi_id
= ENTITY_TYPE_ID
;
341 req
.ID
.toi_entity
.tei_entity
= ent
->tei_entity
;
342 req
.ID
.toi_entity
.tei_instance
= ent
->tei_instance
;
344 status
= DeviceIoControl( tcpFile
,
345 IOCTL_TCP_QUERY_INFORMATION_EX
,
353 TRACE("TdiGetEntityType() => %08x %08x\n", *type
, status
);
355 return (status
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
358 BOOL
hasArp( HANDLE tcpFile
, TDIEntityID
*arp_maybe
) {
359 TCP_REQUEST_QUERY_INFORMATION_EX req
= TCP_REQUEST_QUERY_INFORMATION_INIT
;
360 NTSTATUS status
= STATUS_SUCCESS
;
361 DWORD returnSize
, type
;
363 req
.ID
.toi_class
= INFO_CLASS_GENERIC
;
364 req
.ID
.toi_type
= INFO_TYPE_PROVIDER
;
365 req
.ID
.toi_id
= ENTITY_TYPE_ID
;
366 req
.ID
.toi_entity
.tei_entity
= AT_ENTITY
;
367 req
.ID
.toi_entity
.tei_instance
= arp_maybe
->tei_instance
;
369 status
= DeviceIoControl( tcpFile
,
370 IOCTL_TCP_QUERY_INFORMATION_EX
,
378 if( !NT_SUCCESS(status
) ) return FALSE
;
379 return type
== AT_ENTITY
;
382 static NTSTATUS
getInterfaceInfoSet( HANDLE tcpFile
,
384 PDWORD numInterfaces
) {
386 TDIEntityID
*entIDSet
= 0;
387 NTSTATUS status
= tdiGetEntityIDSet( tcpFile
, &entIDSet
, &numEntities
);
388 IFInfo
*infoSetInt
= 0;
389 BOOL interfaceInfoComplete
;
390 int curInterf
= 0, i
;
392 if (!NT_SUCCESS(status
)) {
393 ERR("getInterfaceInfoSet: tdiGetEntityIDSet() failed: 0x%lx\n", status
);
397 infoSetInt
= HeapAlloc( GetProcessHeap(), 0,
398 sizeof(IFInfo
) * numEntities
);
401 for( i
= 0; i
< numEntities
; i
++ ) {
402 if( isInterface( &entIDSet
[i
] ) ) {
403 infoSetInt
[curInterf
].entity_id
= entIDSet
[i
];
404 status
= tdiGetMibForIfEntity
407 &infoSetInt
[curInterf
].if_info
);
408 TRACE("tdiGetMibForIfEntity: %08x\n", status
);
409 if( NT_SUCCESS(status
) ) {
415 interfaceInfoComplete
= FALSE
;
416 status
= getNthIpEntity( tcpFile
, 0, &ip_ent
);
417 if( NT_SUCCESS(status
) )
418 status
= tdiGetIpAddrsForIpEntity
419 ( tcpFile
, &ip_ent
, &addrs
, &numAddrs
);
420 for( j
= 0; j
< numAddrs
&& NT_SUCCESS(status
); j
++ ) {
421 TRACE("ADDR %d: index %d (target %d)\n", j
, addrs
[j
].iae_index
, infoSetInt
[curInterf
].if_info
.ent
.if_index
);
422 if( addrs
[j
].iae_index
==
423 infoSetInt
[curInterf
].if_info
.ent
.if_index
) {
424 memcpy( &infoSetInt
[curInterf
].ip_addr
,
426 sizeof( addrs
[j
] ) );
435 if (NT_SUCCESS(status
)) {
436 *infoSet
= infoSetInt
;
437 *numInterfaces
= curInterf
;
439 HeapFree(GetProcessHeap(), 0, infoSetInt
);
444 return STATUS_INSUFFICIENT_RESOURCES
;
448 static DWORD
getNumInterfacesInt(BOOL onlyNonLoopback
)
450 DWORD numEntities
, numInterfaces
= 0;
451 TDIEntityID
*entitySet
;
456 status
= openTcpFile( &tcpFile
);
458 if( !NT_SUCCESS(status
) ) {
459 WARN("getNumInterfaces: failed %08x\n", status
);
463 status
= tdiGetEntityIDSet( tcpFile
, &entitySet
, &numEntities
);
465 if( !NT_SUCCESS(status
) ) {
466 WARN("getNumInterfaces: failed %08x\n", status
);
467 closeTcpFile( tcpFile
);
471 for( i
= 0; i
< numEntities
; i
++ ) {
472 if( isInterface( &entitySet
[i
] ) &&
474 (onlyNonLoopback
&& !isLoopback( tcpFile
, &entitySet
[i
] ))) )
478 TRACE("getNumInterfaces: success: %d %d %08x\n",
479 onlyNonLoopback
, numInterfaces
, status
);
481 closeTcpFile( tcpFile
);
483 tdiFreeThingSet( entitySet
);
485 return numInterfaces
;
488 DWORD
getNumInterfaces(void)
490 return getNumInterfacesInt( FALSE
);
493 DWORD
getNumNonLoopbackInterfaces(void)
495 return getNumInterfacesInt( TRUE
);
498 DWORD
getNthInterfaceEntity( HANDLE tcpFile
, DWORD index
, TDIEntityID
*ent
) {
499 DWORD numEntities
= 0;
500 DWORD numInterfaces
= 0;
501 TDIEntityID
*entitySet
= 0;
502 NTSTATUS status
= tdiGetEntityIDSet( tcpFile
, &entitySet
, &numEntities
);
505 if( !NT_SUCCESS(status
) )
508 for( i
= 0; i
< numEntities
; i
++ ) {
509 if( isInterface( &entitySet
[i
] ) ) {
510 if( numInterfaces
== index
) break;
511 else numInterfaces
++;
515 TRACE("Index %d is entity #%d - %04x:%08x\n", index
, i
,
516 entitySet
[i
].tei_entity
, entitySet
[i
].tei_instance
);
518 if( numInterfaces
== index
&& i
< numEntities
) {
519 memcpy( ent
, &entitySet
[i
], sizeof(*ent
) );
520 tdiFreeThingSet( entitySet
);
521 return STATUS_SUCCESS
;
523 tdiFreeThingSet( entitySet
);
524 return STATUS_UNSUCCESSFUL
;
528 NTSTATUS
getInterfaceInfoByIndex( HANDLE tcpFile
, DWORD index
, IFInfo
*info
) {
531 NTSTATUS status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
534 if( NT_SUCCESS(status
) )
535 for( i
= 0; i
< numInterfaces
; i
++ ) {
536 if( ifInfo
[i
].if_info
.ent
.if_index
== index
) {
537 memcpy( info
, &ifInfo
[i
], sizeof(*info
) );
542 if( NT_SUCCESS(status
) )
543 return i
< numInterfaces
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
548 NTSTATUS
getInterfaceInfoByName( HANDLE tcpFile
, char *name
, IFInfo
*info
) {
552 NTSTATUS status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
554 if( NT_SUCCESS(status
) )
555 for( i
= 0; i
< numInterfaces
; i
++ ) {
556 if( !strcmp((PCHAR
)ifInfo
[i
].if_info
.ent
.if_descr
, name
) ) {
557 memcpy( info
, &ifInfo
[i
], sizeof(*info
) );
562 if( NT_SUCCESS(status
) )
563 return i
< numInterfaces
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
568 /* Note that the result of this operation must be freed later */
570 const char *getInterfaceNameByIndex(DWORD index
)
574 char *interfaceName
= 0, *adapter_name
= 0;
575 NTSTATUS status
= openTcpFile( &tcpFile
);
577 if( NT_SUCCESS(status
) ) {
578 status
= getInterfaceInfoByIndex( tcpFile
, index
, &ifInfo
);
580 if( NT_SUCCESS(status
) ) {
581 adapter_name
= (char *)ifInfo
.if_info
.ent
.if_descr
;
583 interfaceName
= HeapAlloc( GetProcessHeap(), 0,
584 strlen(adapter_name
) + 1 );
585 strcpy( interfaceName
, adapter_name
);
588 closeTcpFile( tcpFile
);
591 return interfaceName
;
594 void consumeInterfaceName(const char *name
) {
595 HeapFree( GetProcessHeap(), 0, (char *)name
);
598 DWORD
getInterfaceIndexByName(const char *name
, PDWORD index
)
602 NTSTATUS status
= openTcpFile( &tcpFile
);
604 if( NT_SUCCESS(status
) ) {
605 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &ifInfo
);
607 if( NT_SUCCESS(status
) ) {
608 *index
= ifInfo
.if_info
.ent
.if_index
;
611 closeTcpFile( tcpFile
);
617 InterfaceIndexTable
*getInterfaceIndexTableInt( BOOL nonLoopbackOnly
) {
618 DWORD numInterfaces
, curInterface
= 0;
621 InterfaceIndexTable
*ret
= 0;
623 NTSTATUS status
= openTcpFile( &tcpFile
);
625 if( NT_SUCCESS(status
) ) {
626 status
= getInterfaceInfoSet( tcpFile
, &ifInfo
, &numInterfaces
);
628 TRACE("InterfaceInfoSet: %08x, %04x:%08x\n",
630 ifInfo
->entity_id
.tei_entity
,
631 ifInfo
->entity_id
.tei_instance
);
633 if( NT_SUCCESS(status
) ) {
634 ret
= (InterfaceIndexTable
*)
636 sizeof(InterfaceIndexTable
) +
637 (numInterfaces
- 1) * sizeof(DWORD
));
640 ret
->numAllocated
= numInterfaces
;
641 TRACE("NumInterfaces = %d\n", numInterfaces
);
643 for( i
= 0; i
< numInterfaces
; i
++ ) {
644 TRACE("Examining interface %d\n", i
);
645 if( !nonLoopbackOnly
||
646 !isLoopback( tcpFile
, &ifInfo
[i
].entity_id
) ) {
647 TRACE("Interface %d matches (%d)\n", i
, curInterface
);
648 ret
->indexes
[curInterface
++] =
649 ifInfo
[i
].if_info
.ent
.if_index
;
653 ret
->numIndexes
= curInterface
;
656 tdiFreeThingSet( ifInfo
);
658 closeTcpFile( tcpFile
);
664 InterfaceIndexTable
*getInterfaceIndexTable(void) {
665 return getInterfaceIndexTableInt( FALSE
);
668 InterfaceIndexTable
*getNonLoopbackInterfaceIndexTable(void) {
669 return getInterfaceIndexTableInt( TRUE
);
672 DWORD
getInterfaceIPAddrByName(const char *name
)
677 NTSTATUS
getIPAddrEntryForIf(HANDLE tcpFile
,
683 getInterfaceInfoByName( tcpFile
, name
, ifInfo
) :
684 getInterfaceInfoByIndex( tcpFile
, index
, ifInfo
);
686 if (!NT_SUCCESS(status
)) {
687 ERR("getIPAddrEntryForIf returning %lx\n", status
);
693 DWORD
getAddrByIndexOrName( char *name
, DWORD index
, IPHLPAddrType addrType
) {
696 NTSTATUS status
= STATUS_SUCCESS
;
697 DWORD addrOut
= INADDR_ANY
;
699 status
= openTcpFile( &tcpFile
);
701 if( NT_SUCCESS(status
) ) {
702 status
= getIPAddrEntryForIf( tcpFile
, name
, index
, &ifInfo
);
703 if( NT_SUCCESS(status
) ) {
705 case IPAAddr
: addrOut
= ifInfo
.ip_addr
.iae_addr
; break;
706 case IPABcast
: addrOut
= ifInfo
.ip_addr
.iae_bcastaddr
; break;
707 case IPAMask
: addrOut
= ifInfo
.ip_addr
.iae_mask
; break;
708 case IFMtu
: addrOut
= ifInfo
.if_info
.ent
.if_mtu
; break;
709 case IFStatus
: addrOut
= ifInfo
.if_info
.ent
.if_operstatus
; break;
712 closeTcpFile( tcpFile
);
718 DWORD
getInterfaceIPAddrByIndex(DWORD index
) {
719 return getAddrByIndexOrName( 0, index
, IPAAddr
);
722 DWORD
getInterfaceBCastAddrByName(const char *name
) {
723 return getAddrByIndexOrName( (char *)name
, 0, IPABcast
);
726 DWORD
getInterfaceBCastAddrByIndex(DWORD index
) {
727 return getAddrByIndexOrName( 0, index
, IPABcast
);
730 DWORD
getInterfaceMaskByName(const char *name
) {
731 return getAddrByIndexOrName( (char *)name
, 0, IPAMask
);
734 DWORD
getInterfaceMaskByIndex(DWORD index
) {
735 return getAddrByIndexOrName( 0, index
, IPAMask
);
738 void getInterfacePhysicalFromInfo( IFInfo
*info
,
739 PDWORD len
, PBYTE addr
, PDWORD type
) {
740 *len
= info
->if_info
.ent
.if_physaddrlen
;
741 memcpy( addr
, info
->if_info
.ent
.if_physaddr
, *len
);
742 *type
= info
->if_info
.ent
.if_type
;
745 DWORD
getInterfacePhysicalByName(const char *name
, PDWORD len
, PBYTE addr
,
750 NTSTATUS status
= openTcpFile( &tcpFile
);
752 if( NT_SUCCESS(status
) ) {
753 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &info
);
754 if( NT_SUCCESS(status
) )
755 getInterfacePhysicalFromInfo( &info
, len
, addr
, type
);
756 closeTcpFile( tcpFile
);
762 DWORD
getInterfacePhysicalByIndex(DWORD index
, PDWORD len
, PBYTE addr
,
767 NTSTATUS status
= openTcpFile( &tcpFile
);
769 if( NT_SUCCESS(status
) ) {
770 status
= getInterfaceInfoByIndex( tcpFile
, index
, &info
);
771 if( NT_SUCCESS(status
) )
772 getInterfacePhysicalFromInfo( &info
, len
, addr
, type
);
773 closeTcpFile( tcpFile
);
779 DWORD
getInterfaceMtuByName(const char *name
, PDWORD mtu
) {
780 *mtu
= getAddrByIndexOrName( (char *)name
, 0, IFMtu
);
781 return STATUS_SUCCESS
;
784 DWORD
getInterfaceMtuByIndex(DWORD index
, PDWORD mtu
) {
785 *mtu
= getAddrByIndexOrName( 0, index
, IFMtu
);
786 return STATUS_SUCCESS
;
789 DWORD
getInterfaceStatusByName(const char *name
, PDWORD status
) {
790 *status
= getAddrByIndexOrName( (char *)name
, 0, IFStatus
);
791 return STATUS_SUCCESS
;
794 DWORD
getInterfaceStatusByIndex(DWORD index
, PDWORD status
)
796 *status
= getAddrByIndexOrName( 0, index
, IFStatus
);
797 return STATUS_SUCCESS
;
800 DWORD
getInterfaceEntryByName(const char *name
, PMIB_IFROW entry
)
804 NTSTATUS status
= openTcpFile( &tcpFile
);
808 if( NT_SUCCESS(status
) ) {
809 status
= getInterfaceInfoByName( tcpFile
, (char *)name
, &info
);
811 if( NT_SUCCESS(status
) ) {
812 memcpy( &entry
->wszName
[MAX_INTERFACE_NAME_LEN
],
814 sizeof(info
.if_info
) );
817 TRACE("entry->bDescr = %s\n", entry
->bDescr
);
819 closeTcpFile( tcpFile
);
825 DWORD
getInterfaceEntryByIndex(DWORD index
, PMIB_IFROW entry
)
829 NTSTATUS status
= openTcpFile( &tcpFile
);
833 if( NT_SUCCESS(status
) ) {
834 status
= getInterfaceInfoByIndex( tcpFile
, index
, &info
);
836 if( NT_SUCCESS(status
) ) {
837 memcpy( &entry
->wszName
[MAX_INTERFACE_NAME_LEN
],
839 sizeof(info
.if_info
) );
842 closeTcpFile( tcpFile
);
848 char *toIPAddressString(unsigned int addr
, char string
[16])
851 struct in_addr iAddr
;
854 /* extra-anal, just to make auditors happy */
855 strncpy(string
, inet_ntoa(iAddr
), 16);
861 NTSTATUS
addIPAddress( IPAddr Address
, IPMask Mask
, DWORD IfIndex
,
862 PULONG NteContext
, PULONG NteInstance
)
865 NTSTATUS status
= openTcpFile( &tcpFile
);
867 IO_STATUS_BLOCK Iosb
;
871 if( !NT_SUCCESS(status
) ) return status
;
873 Data
.NteContext
= IfIndex
;
874 Data
.NewAddress
= Address
;
875 Data
.NewNetmask
= Mask
;
877 status
= NtDeviceIoControlFile( tcpFile
,
882 IOCTL_SET_IP_ADDRESS
,
888 closeTcpFile( tcpFile
);
890 if( NT_SUCCESS(status
) ) {
891 *NteContext
= Iosb
.Information
;
892 *NteInstance
= Data
.NewAddress
;
895 if (!NT_SUCCESS(status
)) {
896 ERR("addIPAddress for if %d returning 0x%lx\n", IfIndex
, status
);
903 NTSTATUS
deleteIpAddress( ULONG NteContext
)
906 NTSTATUS status
= openTcpFile( &tcpFile
);
907 IO_STATUS_BLOCK Iosb
;
911 if( !NT_SUCCESS(status
) ) return status
;
913 status
= NtDeviceIoControlFile( tcpFile
,
918 IOCTL_DELETE_IP_ADDRESS
,
924 closeTcpFile( tcpFile
);
926 if (!NT_SUCCESS(status
)) {
927 ERR("deleteIpAddress(%lu) returning 0x%lx\n", NteContext
, status
);